SQL Server笔记 -- 第50章 存储过程

在 SQL Server 中,存储过程是可接收参数的可复用程序,不返回值(如函数那样),但可返回执行状态。

第50.1节 创建并执行基本存储过程

使用 Library 数据库的 Authors 表:

sql 复制代码
CREATE PROCEDURE GetName
    @input_id INT = NULL,        -- 输入参数:人员 ID,默认 NULL
    @name    VARCHAR(128) = NULL -- 输入参数:姓名,默认 NULL
AS
BEGIN
    SELECT Name + ' is from ' + Country
    FROM Authors
    WHERE Id = @input_id OR Name = @name;
END
GO

执行方式:

  1. 使用 EXECUTE / EXEC
sql 复制代码
EXECUTE GetName @input_id = 1;
EXEC GetName @name = 'Ernest Hemingway';
  1. 省略 EXEC,直接调用
sql 复制代码
GetName NULL, 'Ernest Hemingway';
  1. 参数顺序可任意,只要显式指定:
sql 复制代码
CREATE PROC dbo.sProcTemp
    @Param1 INT,
    @Param2 INT
AS
SELECT Param1 = @Param1, Param2 = @Param2;

-- 调用
EXEC dbo.sProcTemp @Param2 = 0, @Param1 = 1;
  1. sp_ 开头并放在 master 数据库中的存储过程可在任意数据库中直接调用(优先搜索 master)。

第50.2节 带 IF...ELSE 与 INSERT 的存储过程

示例表:

sql 复制代码
CREATE TABLE Employee (
    Id          INT,
    EmpName     VARCHAR(25),
    EmpGender   VARCHAR(6),
    EmpDeptId   INT
);

存储过程:检查参数非空后插入。

sql 复制代码
CREATE PROCEDURE spSetEmployeeDetails
    @ID       INT,
    @Name     VARCHAR(25),
    @Gender   VARCHAR(6),
    @DeptId   INT
AS
BEGIN
    IF (
        @ID IS NOT NULL AND LEN(@ID) != 0
        AND @Name IS NOT NULL AND LEN(@Name) != 0
        AND @Gender IS NOT NULL AND LEN(@Gender) != 0
        AND @DeptId IS NOT NULL AND LEN(@DeptId) != 0
    )
    BEGIN
        INSERT INTO Employee (Id, EmpName, EmpGender, EmpDeptId)
        VALUES (@ID, @Name, @Gender, @DeptId);
    END
    ELSE
        PRINT 'Incorrect Parameters';
END
GO

调用:

sql 复制代码
DECLARE @ID INT, @Name VARCHAR(25), @Gender VARCHAR(6), @DeptId INT;

EXEC spSetEmployeeDetails
    @ID = 1,
    @Name = 'Subin Nepal',
    @Gender = 'Male',
    @DeptId = 182666;

第50.3节 存储过程中的动态 SQL

当表名、列名或过滤值需在运行时决定,可拼接并执行动态 SQL。

sql 复制代码
CREATE PROC sp_dynamicSQL
    @table_name NVARCHAR(20),
    @col_name   NVARCHAR(20),
    @col_value  NVARCHAR(20)
AS
BEGIN
    DECLARE @Query NVARCHAR(MAX);
    SET @Query = 'SELECT * FROM ' + QUOTENAME(@table_name)
               + ' WHERE ' + QUOTENAME(@col_name) + ' = @val';
    EXEC sp_executesql @Query, N'@val NVARCHAR(20)', @val = @col_value;
END

调用:

sql 复制代码
DECLARE @table NVARCHAR(20) = 'ITCompanyInNepal',
        @col   NVARCHAR(20) = 'Headquarter',
        @val   NVARCHAR(20) = 'USA';

EXEC sp_dynamicSQL @table, @col, @val;
  • 使用 QUOTENAME 避免注入
  • 复杂场景可拼接更长脚本,实现多表/多条件动态查询

第50.4节 带 OUTPUT 参数的存储过程

存储过程可通过 OUTPUT 关键字返回值。

  1. 单输出参数示例
sql 复制代码
CREATE PROC SprocWithOutParams
    @InParam  VARCHAR(30),
    @OutParam VARCHAR(30) OUTPUT
AS
BEGIN
    SET @OutParam = @InParam + ' must come out';
    RETURN;
END
GO

-- 调用
DECLARE @Out VARCHAR(30);
EXEC SprocWithOutParams 'what goes in', @Out OUTPUT;
PRINT @Out;
  1. 多输出参数
sql 复制代码
CREATE PROC SprocWithOutParams2
    @InParam  VARCHAR(30),
    @Out1     VARCHAR(30) OUTPUT,
    @Out2     VARCHAR(30) OUTPUT
AS
BEGIN
    SET @Out1 = @InParam + ' must come out';
    SET @Out2 = @InParam + ' must come out';
    RETURN;
END
GO

-- 调用
DECLARE @O1 VARCHAR(30), @O2 VARCHAR(30);
EXEC SprocWithOutParams2 'what goes in', @O1 OUTPUT, @O2 OUTPUT;
PRINT @O1; PRINT @O2;

第50.5节 简单循环(遍历)

先准备临时数据:

sql 复制代码
SELECT
    o.name,
    ROW_NUMBER() OVER (ORDER BY o.name) AS rn
INTO #systables
FROM sys.objects o
WHERE o.type = 'S';

循环脚本:

sql 复制代码
DECLARE @rn INT = 1, @maxRn INT = (SELECT MAX(rn) FROM #systables);
DECLARE @tablename SYSNAME;

WHILE @rn <= @maxRn
BEGIN
    SELECT @tablename = name, @rn = @rn + 1
    FROM #systables
    WHERE rn = @rn;

    PRINT @tablename;
END

第50.6节 简单循环(指定次数打印)

sql 复制代码
CREATE PROC SprocWithSimpleLoop
    @SayThis      VARCHAR(30),
    @ThisManyTimes INT
AS
BEGIN
    WHILE @ThisManyTimes > 0
    BEGIN
        PRINT @SayThis;
        SET @ThisManyTimes = @ThisManyTimes - 1;
    END
    RETURN;
END
GO

调用:

sql 复制代码
EXEC SprocWithSimpleLoop 'Hello, World!', 3;

输出:

复制代码
Hello, World!
Hello, World!
Hello, World!
相关推荐
数安3000天16 分钟前
数据分类分级产品有哪四类技术路线?
大数据·数据库
泡茶喝茶写代码18 分钟前
量化数据开发实战系列(第 25 篇):基金基础接口实战:基金列表、ETF-LOF 分类、基金概况、净值数据
java·数据库·人工智能·python·mysql
张小姐的猫22 分钟前
【AI大模型接入SDK】 —— 数据管理 & 与Session模块进行联动
数据结构·数据库·c++·人工智能·python·chatgpt
chnyi6_ya31 分钟前
论文阅读笔记:VBVR-Pro 把「用生成来推理」变成一个可训练、可验证、可优化的闭环
论文阅读·笔记
contro1_h1 小时前
关于ArcGIS许可管理器服务无法启动的问题
经验分享·笔记·学习方法
IvorySQL1 小时前
PostgreSQL 日报|大模型破解在线校验和(9 月 15 日)
数据库·人工智能·postgresql
1314lay_10071 小时前
SQL SERVER 修改已创建的表
经验分享·笔记
東隅已逝,桑榆非晚1 小时前
vector(模拟实现)
c++·笔记·学习
Leon-Ning Liu2 小时前
Oracle 19c ASMB 进程 PGA 内存泄漏排查实战 (Bug 38610635)
数据库·oracle
步行cgn2 小时前
Spring 注入 null 和空字符串详解
数据库·spring·oracle