必须将每个存储过程导出为独立的.sql文件才能纳入git版本控制,因存储过程存于数据库内部,git无法跟踪数据库状态变更;直接执行alter procedure而不导出文件会导致git日志仅存最新快照,丢失真实演进路径。

必须把每个存储过程导出为独立的 .sql 文件才能进 Git,否则 Git 完全看不见变更——这不是建议,是硬性前提。
为什么不能直接 git add 存储过程?
SQL Server、PostgreSQL、MySQL 的存储过程都存在数据库内部,Git 只能跟踪文件系统里的文本。你执行 ALTER PROCEDURE 后,数据库里变了,但磁盘上没对应文件,Git 就像瞎了一样。
常见错误现象:
- 只备份当前
CREATE PROCEDURE语句,漏掉历史ALTER记录 → Git 日志只剩“最新快照”,不是真实演进路径 - 用 SSMS “生成脚本”覆盖本地文件,但默认不带
IF EXISTS判断 → 下次执行报错There is already an object named 'xxx' - 提交信息写 “fix proc bug” → 审计时根本没法定位是改了参数校验,还是绕过了缓存逻辑
怎么导出才可靠?按数据库选命令
不同数据库导出方式差异大,用错工具会导致定义不全、换行错乱或权限污染。
- SQL Server:优先用
SqlPackage.exe /Action:Extract生成.sql文件;比 SSMS 导出更稳定,自带IF OBJECT_ID(...) IS NOT NULL DROP+GO分隔 - PostgreSQL:用
pg_dump --schema-only --no-owner --no-privileges -f procedures.sql,但注意它默认不输出完整CREATE OR REPLACE FUNCTION;补全需配合SELECT pg_get_functiondef('schema.func_name'::regproc) - MySQL:禁用
SHOW CREATE PROCEDURE直接写入文件(含不可见换行,Git 可能判为二进制);改用mysqldump --no-create-info --no-data --routines
Git 提交前必须检查的三件事
光有文件不够,提交动作本身要带约束,否则团队协作会迅速失控。
- 文件命名必须带序号和语义,比如
002_add_usp_get_user.sql,确保按字母序执行;建表脚本没跑完,就别定义引用它的存储过程 - 每个
.sql文件开头加注释块,写清:适用数据库名、依赖的表/函数、修改人、日期、变更摘要 - CI 流水线里加校验:
git status --porcelain检查procedures/usp_calculate_report.sql是否未跟踪或已改未暂存,命中就exit 1
代码审查时重点盯什么?
存储过程的 diff 很容易掩盖真实变更,审查不能只看语法,得看行为影响。
- 检查是否用了
DROP + CREATE替代裸CREATE或ALTER;SQL Server 必须有GO分隔,PostgreSQL 的DROP FUNCTION IF EXISTS必须写全参数类型 - 确认有没有硬编码数据库名或服务器名;应改用
$(DatabaseName)+ SQLCMD 模式,方便多环境部署 - 如果修改涉及公共函数(如
fn_parse_json),提交信息必须说明影响范围:“update fn_parse_json → affects usp_get_order, usp_sync_customer”
最常被忽略的是:导出脚本后没立刻 git add,或者多人同时改一个过程却没同步覆盖本地文件——pre-commit hook 自动拉取定义能缓解,但得加判断:如果文件已被别人修改且未 commit,别粗暴覆盖。











