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!
相关推荐
奇树谦9 分钟前
NAS + 对象存储 + LMDB/HDF5:海量小文件存储最佳实践
数据库
Csvn11 分钟前
📊 SQL 入门 Day 13:窗口函数进阶
后端·sql
观远数据25 分钟前
决策闭环的第三公里:从洞察到行动之间,AI能补上什么
大数据·数据库·人工智能
Mxzx品牌33 分钟前
佛山招聘软件哪个好:【帅聘网】匹配度高
笔记·其他·生活
九硕智慧建筑一体化厂家1 小时前
无线动能开关|烘焙后厨防潮免布线照明控制方案
运维·笔记·智慧城市
满昕欢喜1 小时前
2.4 本地服务器组和中央管理服务器
数据库·sqlserver
空堂与归1 小时前
Python 操作 MySQL 与 Redis:AI 应用的数据读写双引擎
数据库
2401_873479401 小时前
IPv6查出来的地理位置是错的?用双栈IP库解决定位偏差问题
网络·数据库·tcp/ip·ip
ZZHow10241 小时前
PyTorch深度学习入门笔记(小土堆)P7-14
人工智能·pytorch·笔记·python·深度学习
CNSSIRD数据库2 小时前
中国创新型中小企业研究数据库2022-2026
大数据·数据库·数据分析·论文笔记