应统一存储过程参数命名为@p_前缀+小写下划线风格,如@p_user_id;输出参数加_out后缀;需配合依赖检查、调用方更新及头部注释,并通过CI阶段SQL Lint强制执行。

存储过程参数命名不统一,导致调用方难以理解
SQL 存储过程中参数名五花八门:@UserID、@user_id、@p_id、@in_userId……调用时得翻源码猜含义,协作和维护成本直线上升。
核心是建立可执行的命名契约,不是写文档。推荐统一用 @p_ 前缀 + 小写下划线风格,比如 @p_user_id、@p_is_active、@p_created_after。
- 前缀
@p_明确标识这是「parameter」,和变量@temp_id、游标@cur严格区分开 - 全小写 + 下划线(snake_case)兼容 SQL Server / PostgreSQL / MySQL(大小写敏感环境不出错)
- 避免缩写歧义:
@p_usr不如@p_user_id直观;@p_st是 status 还是 start_time? - 输出参数加
_out后缀:@p_user_name_out,比单纯@user_name更易识别方向
SQL Server 中 ALTER PROCEDURE 时不校验参数名变更影响
改了 @uid 为 @p_user_id,但调用方代码还传 @uid,运行时报错 Procedure or function 'xxx' expects parameter '@uid', which was not supplied. —— 这类错误不会在 ALTER 时暴露,只在运行时炸。
必须配合三步动作:
- ALTER 前先查依赖:
SELECT * FROM sys.dm_exec_describe_first_result_set(N'EXEC your_proc @uid=1', NULL, 0)看当前期望参数 - 更新所有调用方:应用层代码、其他存储过程里的
EXEC your_proc @uid = ...、SSIS 包、报表数据集 - 在存储过程头部加注释块,明确标注参数契约:
-- @p_user_id: INT, required, ID of target user
MySQL 存储过程中 IN/OUT/INOUT 参数类型与命名需同步约束
MySQL 允许 IN user_id INT 这种省略 @ 的写法,但混用风格会让团队困惑。更麻烦的是:类型不一致引发隐式转换,比如 IN user_id VARCHAR(20) 被传入数字 123,可能匹配到 '123 '(带空格)。
强制约定:
- 一律使用
@p_前缀 + 显式声明IN/OUT:IN @p_user_id BIGINT,不省略@ - 输入参数类型必须和业务字段一致:用户表主键是
BIGINT,参数就不能用INT或VARCHAR -
OUT参数命名必须带_out,且类型要和返回值语义对齐:OUT @p_total_count_out INT,而不是模糊的@p_cnt
跨数据库迁移时参数命名规则被忽略,引发兼容性断裂
从 SQL Server 迁到 PostgreSQL,原 @p_user_id 在 PG 里不合法(PG 参数用 $1, $2 或命名参数但语法不同),硬套命名会直接报错 ERROR: unexpected parameter name。
应对逻辑不是“统一命名”,而是“统一抽象”:
- 在应用层封装调用,把
@p_user_id映射为 PG 的$1或命名参数user_id(PG 14+ 支持user_id => 123) - 存储过程本身按目标库习惯重写:PG 推荐用
IN user_id BIGINT(无@),但函数签名注释仍保持-- p_user_id: user identifier - 禁止在跨库项目中复用同一份 .sql 文件——命名只是表象,底层参数机制差异才是真坑
参数命名规范真正难的不是定规则,而是让所有人每次写 CREATE PROCEDURE 时,手指下意识敲出 @p_ 而不是 @ 或直接 user_id。这需要 CI 阶段加 SQL Lint 规则(比如检测 CREATE PROCEDURE.*@[^p_]),光靠 Code Review 守不住。










