CREATE PROCEDURE 是创建存储过程的唯一标准方式,必须用 GO 分隔批处理、显式声明参数默认值、避免 sp_ 前缀、带架构名、执行后验证 sys.procedures 确认创建成功。

CREATE PROCEDURE 是创建存储过程的唯一标准方式,没有快捷按钮或向导能替代它。直接写语句、执行、验证,是最稳也最快的路径。
用 CREATE PROCEDURE 写完必须立刻 GO
SQL Server 把 CREATE PROCEDURE 当作一个独立批处理,不允许和前面的 USE 或后面的 EXEC 写在同一段里。常见错误是这样写:
USE MyDB<br>CREATE PROCEDURE GetUsers AS SELECT * FROM Users
这会报错:Incorrect syntax near 'CREATE'。正确写法必须用 GO 分隔:
USE MyDB<br>GO<br>CREATE PROCEDURE GetUsers AS SELECT * FROM Users<br>GO
-
GO不是 T-SQL 语句,是 SSMS / sqlcmd 的批处理分隔符,缺了就编译失败 - 如果在脚本里混用了
ALTER PROCEDURE和CREATE PROCEDURE,也要各自用GO隔开 - 建完不执行
GO,哪怕语法没错,过程也不会被真正创建到数据库中
@parameter 默认可空,但别依赖它
声明参数时不加 = NULL,SQL Server 仍允许调用时传 NULL,但一旦这个值进到 INSERT 或 WHERE 里,可能触发意外逻辑——比如 WHERE Status = @status 在 @status 为 NULL 时永远不匹配。
- 显式写默认值更安全:
@status VARCHAR(20) = 'Active' - 需要支持
NULL语义时,改用IS NULL或IS NOT NULL判断,而不是等值比较 - 输出参数必须带
OUTPUT关键字,漏写会导致调用时值不回传,但不会报错
别用 sp_ 前缀,哪怕只是测试
SQL Server 遇到以 sp_ 开头的过程名,会先查 master 数据库里的系统过程,再查当前库。如果你建了 sp_GetUser,而某天 SQL Server 更新后自带同名系统过程,你的代码就静默失效了。
- 用
usp_(user stored procedure)或业务前缀如acc_GetUser更稳妥 - 临时过程用
#开头(局部)或##(全局),但只在调试或会话级场景用,别放生产 - 过程名要带架构,比如
dbo.GetUser,避免跨库调用时解析歧义
调试前先确认是否真被创建成功
很多人卡在“断点不命中”,结果发现根本没创建成功——SSMS 对象资源管理器里看不到新过程,或者 EXEC GetUser 报错 Could not find stored procedure。
- 执行完
CREATE PROCEDURE后,立刻查sys.procedures:SELECT name FROM sys.procedures WHERE name = 'GetUser' - 如果没结果,说明前面的
GO缺失、数据库上下文不对(比如在master里建却想在MyDB里调)、或权限不足(缺少CREATE PROCEDURE权限) - SSMS 调试功能只对已存在且可执行的过程有效,没创建成功的对象连断点都设不上
真正麻烦的不是语法,而是隐式依赖:当前数据库上下文、批处理边界、命名冲突、权限链。每一步都得亲手验证,不能凭“应该可以”去推进。

















