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!
相关推荐
IvorySQL10 小时前
PostgreSQL 技术日报 (3月7日)|生态更新与内核性能讨论
数据库·postgresql·开源
赵渝强老师11 小时前
【赵渝强老师】金仓数据库的数据文件
数据库·国产数据库·kingbase·金仓数据库
随逸17714 小时前
《Milvus向量数据库从入门到实战,手把手搭建语义检索系统》
数据库
神秘的猪头15 小时前
🚀 React 开发者进阶:RAG 核心——手把手带你玩转 Milvus 向量数据库
数据库·后端·llm
齐生11 天前
iOS 知识点 - 渲染机制、动画、卡顿小集合
笔记
IvorySQL1 天前
PostgreSQL 技术日报 (3月6日)|为什么 Ctrl-C 在 psql 里让人不安?
数据库·postgresql·开源
NineData1 天前
数据库管理工具NineData,一年进化成为数万+开发者的首选数据库工具?
运维·数据结构·数据库
用户962377954482 天前
VulnHub DC-1 靶机渗透测试笔记
笔记·测试
IvorySQL2 天前
PostgreSQL 技术日报 (3月5日)|规划器控制力升级,内核能力再进阶
数据库·postgresql·开源