create procedure 是唯一入口,需带 as 和 begin/end 包裹语句;参数声明在 as 前,变量定义在 begin 后;return 仅返回整数状态码,业务数据用 output 参数或 select 结果集;exec 调用不共享变量和事务,跨库用三段式名;调试需验证运行逻辑、null 处理及动态 sql 安全性。

直接上手写,CREATE PROCEDURE 是唯一入口,没别的捷径。别被“过程”俩字吓住——它就是带参数的 SQL 批处理,只是编译后存进数据库里,下次调用更快、更安全。
怎么写基础结构?必须带 AS 和 BEGIN/END
SQL Server 不接受裸露的语句块。哪怕只有一行 SELECT,也得包在 BEGIN...END 里,否则报错 Incorrect syntax near 'AS'。
-
CREATE PROCEDURE后面不能跟括号空参,哪怕没参数也要留空格再写AS - 参数声明必须写在
AS前,格式是@param_name datatype,比如@id INT,不能写成id INT - 所有变量定义(
DECLARE @var INT)必须放在BEGIN之后、第一个可执行语句之前,否则报Must declare the scalar variable
正确示例:
CREATE PROCEDURE GetOrderCount @customer_id INT
AS
BEGIN
DECLARE @cnt INT;
SELECT @cnt = COUNT(*) FROM Orders WHERE CustomerID = @customer_id;
SELECT @cnt AS TotalOrders;
END
怎么传参和返回结果?别混淆 OUTPUT 和 RETURN
RETURN 只能返回一个整数状态码(比如 0 成功、1 失败),不是业务数据;真正要给调用方“返回值”,得靠 OUTPUT 参数或 SELECT 结果集。
- 加
OUTPUT关键字才能把参数当输出用:@total_count INT OUTPUT - 调用时也得显式标出
OUTPUT:EXEC GetTotal @t OUT,漏掉OUT就收不到值 - 如果想返回表格数据,直接
SELECT就行,不用声明任何东西——但注意:多个SELECT会生成多个结果集,客户端得按顺序读取 -
RETURN值默认是 0,手动设RETURN 5后,调用方可用@@ERROR或EXEC @ret = proc_name捕获
怎么调用另一个存储过程?EXEC 最简,但注意上下文隔离
用 EXEC 或 EXECUTE 调用就行,参数照常传。但关键点在于:被调用的过程和当前过程**不共享变量、临时表、事务状态**。
- 临时表
#tmp在调用链里不自动透传,想传数据得用表变量@table_var或物理中间表 - 如果外层开了事务,内层
ROLLBACK会直接炸掉整个事务,除非内层用SAVE TRANSACTION设保存点 - 嵌套太深(>32 层)会触发
Maximum stored procedure, function, trigger, or view nesting level exceeded - 跨库调用要写三段式名:
EXEC OtherDB.dbo.RemoteProc @x = 1
怎么调试和验证?别只看“执行成功”
SSMS 里点“执行”按钮只告诉你语法对不对,真正的坑在运行时逻辑里。
- 先用
SET NOCOUNT ON开头,避免xx 行受影响消息干扰结果集解析 - 参数为空或 NULL 时,
WHERE col = @p会漏掉所有 NULL 行,得写成WHERE (@p IS NULL OR col = @p) - 动态 SQL(
EXEC sp_executesql)里拼接字符串极易 SQL 注入,参数化是唯一解法 - 修改已有过程用
ALTER PROCEDURE,别删了重建——权限、依赖关系全丢了
最常被跳过的一步:检查 sys.procedures 和 sys.parameters 视图,确认参数类型、是否 OUTPUT、默认值是否生效。光看代码容易误判。











