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!
相关推荐
寒秋花开曾相惜2 小时前
(学习笔记)2.1 信息存储(2.1.1 十六进制表示法)
笔记·学习
LSL666_2 小时前
10 集群
java·开发语言·数据库·redis·集群
TDengine (老段)2 小时前
TDengine IDMP 数据可视化 7. 事件列表
大数据·数据库·人工智能·物联网·时序数据库·tdengine·涛思数据
SQL必知必会2 小时前
SQL 条件聚合:超越基础 GROUP BY
数据库·sql
hacklf20082 小时前
数据库高安全—openGauss安全整体架构&安全认证
数据库·安全·架构
全栈前端老曹2 小时前
【Redis】 监控与慢查询日志 —— slowlog、INFO 命令、RedisInsight 可视化监控
前端·数据库·redis·缓存·全栈·数据库监控·slowlog
知识分享小能手2 小时前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019 规则、默认值和完整性约束 —— 语法详解与实战案例(11)
sql·学习·sqlserver
木子欢儿2 小时前
debian 13 安装配置ftp 创建用户admin可以访问 /mnt/Data/
linux·运维·服务器·数据库·debian
LSL666_2 小时前
3 Redis 的 Java 客户端
java·数据库·redis