必须将存储过程导出为纯文本SQL文件才能纳入Git版本控制,因SQL Server、PostgreSQL、MySQL的存储过程均存于数据库内部,Git无法跟踪数据库状态变更;直接执行ALTER PROCEDURE而不导出文件会导致Git日志仅存最新快照,丢失真实演进路径。

必须把存储过程导出为纯文本 SQL 文件才能进 Git,否则 Git 完全看不见变更——这不是可选项,是硬性前提。
为什么不能直接 git add 存储过程?
SQL Server、PostgreSQL、MySQL 的存储过程都存在数据库内部,Git 只能跟踪文件系统里的文本。你执行 ALTER PROCEDURE 后,数据库里变了,但本地磁盘上没对应文件,Git 就像瞎了一样。
- 常见错误:只备份当前
CREATE PROCEDURE语句,漏掉历史ALTER记录 → Git 日志只剩“最新快照”,不是真实演进路径 - SQL Server 推荐用
sqlpackage.exe /Action:Extract生成 .sql 文件,比 SSMS “生成脚本”更可靠(后者常缺IF EXISTS判断) - PostgreSQL 用
pg_dump --schema-only --no-owner --no-privileges -f procedures.sql,但注意它默认不带CREATE OR REPLACE FUNCTION完整定义,得配合pg_get_functiondef()手动补 - MySQL 要警惕
SHOW CREATE PROCEDURE返回结果含换行和注释,直接写入文件可能被 Git 误判为二进制;建议用mysqldump --no-create-info --no-data --routines
怎么让每次修改都自动同步到 Git?
靠人肉记得导出 + 提交,三次里至少两次会漏。必须把导出动作固化进流程。
- CI 流水线里加校验:
git status --porcelain检查procedures/usp_calculate_report.sql是否未跟踪或已改未暂存,命中就exit 1 - 本地 pre-commit hook 可调脚本自动拉取所有 procedure 定义并覆盖对应文件,但要加判断:如果文件已被别人修改且未 commit,别粗暴覆盖
- 禁止在生产库直连执行
ALTER PROCEDURE—— 所有变更必须走 Git merge → 自动化部署脚本(如 Flyway)回放 SQL 文件
SQL 文件怎么写才不怕重复执行失败?
裸写 CREATE PROCEDURE 在 CI 或重装库时必然报错 “There is already an object named 'xxx'”,根本跑不通。
- SQL Server 必须用
IF OBJECT_ID('usp_get_user','P') IS NOT NULL DROP PROCEDURE usp_get_user;+GO+CREATE PROCEDURE组合,GO是关键分隔符,不能省 - PostgreSQL 直接用
DROP FUNCTION IF EXISTS my_func(integer),但参数类型必须写全,否则删不掉旧版本 - 文件名带序号和语义,比如
002_add_usp_get_user.sql,确保按字母序执行;建表脚本没跑完,就别定义引用它的存储过程 - 别把不同环境的开关变更(如
SET ANSI_NULLS ON)混进业务逻辑脚本,单独拆成003_fix_ansi_nulls.sql,方便回滚
提交信息怎么写才能支撑真正审计?
写 “fix bug in proc” 这类信息等于没写。审计时你要快速定位:这个修复到底改了参数校验?还是绕过了缓存?
- 提交信息必须锚定具体逻辑变化,例如:“修复 usp_calculate_report 中空订单状态导致的空结果集,增加 ISNULL(@status, 'pending') 默认值”
- 当多个 procedure 共享公共函数(如都调用
fn_parse_json),一次函数修改可能引发连锁反应,提交信息得写明影响范围:“更新 fn_parse_json v2.1,影响 usp_calculate_report、usp_sync_data 两个过程的 JSON 解析行为” - 每个 .sql 文件开头加注释块,写清适用库名、依赖对象、修改人、日期、变更摘要;避免硬编码数据库名,用
$(DatabaseName)+ SQLCMD 模式适配多环境
最易被忽略的点:Dolt 等支持内置版本控制的数据库,也得显式调用 dolt_commit 才算真正存档——执行完 10 条 ALTER TABLE,只要没调这句,关掉连接就全丢。没有隐式 save,也没有 auto-commit。

















