直接用sys.triggers+object_definition()可轻量导出触发器脚本,但加密触发器返回null且无提示;需加where parent_class=1过滤表级触发器,用sqlcmd直出文件并加-u避免乱码,ssms生成脚本需手动勾选触发器且配置高级选项。

直接用 sys.triggers + OBJECT_DEFINITION() 就能取定义,但加密触发器会返回 NULL
SQL Server 的 sys.triggers 视图能列出所有触发器,OBJECT_DEFINITION() 函数可提取其完整 CREATE 语句——这是最轻量、无需 SSMS 图形界面的方案。但必须提前知道:如果触发器被创建时加了 WITH ENCRYPTION,OBJECT_DEFINITION() 会直接返回 NULL,且不报错、无提示,容易误以为“没查到”。
- 基础查询必须加
WHERE parent_class = 1(表示绑定到表),否则会混入数据库级触发器(如 LOGON 触发器) - 别漏掉 schema 前缀:
[sales].[trg_update_order]和[dbo].[trg_update_order]是两个独立对象 - 若目标库要复用脚本,需手动替换
CREATE DEFINER类内容(SQL Server 没这字段,但可能含EXECUTE AS子句,权限上下文得核对)
用 SQLCMD 批量导出到文件,避免复制粘贴出错
SSMS 查询窗口输出超过几千行后容易卡顿或截断,人工复制极易丢内容。用 sqlcmd 命令行工具直出文件更稳,还能加 -u(Unicode)避免中文乱码。
- 命令示例:
sqlcmd -S myserver -d mydb -U sa -P password -Q "SELECT OBJECT_DEFINITION(object_id) FROM sys.triggers WHERE parent_class = 1 AND is_ms_shipped = 0" -o triggers.sql -u -
-o输出文件默认是 ANSI 编码,加-u才能正确保存中文注释或 Unicode 字符 - 若某触发器加密了,输出里对应位置就是空行——得靠前后行数差反推哪些缺失,建议先导出触发器名列表比对:
SELECT name FROM sys.triggers WHERE parent_class = 1 AND is_ms_shipped = 0
SSMS “生成脚本”向导默认不包含触发器,必须手动勾选
在数据库节点右键 → “任务” → “生成脚本”,即使勾选了“整个数据库”,触发器也不会自动包含。这是 SSMS 的默认行为,不是 bug。
- 必须进入“选择对象”页,展开“程序性对象” → “触发器”,再勾选——不能只勾“整个数据库”就以为万事大吉
- 勾选后,高级选项里至少改三项:
Script DROP and CREATE设为True(避免重复建时报错)、Script USE DATABASE设为True(确保脚本开头有USE [db])、Include IF NOT EXISTS建议打开(防重复执行) - 导出为“每个对象一个文件”比单文件更易管理,尤其当触发器上百个时,文件名就是
triggername.sql,不用再拆分
跨库部署前务必检查 DEFINER 和 EXECUTE AS 权限上下文
SQL Server 不像 MySQL 那样有 DEFINER 字段,但它支持 EXECUTE AS 子句,而该子句里的登录名(如 EXECUTE AS OWNER 或 EXECUTE AS 'sa')在目标库可能不存在或权限不足。
- 导出脚本里搜
EXECUTE AS,确认目标库是否存在对应主体(login / user / role) - 若用
EXECUTE AS OWNER,需保证源库和目标库中该触发器所属 schema 的 owner 是同一登录名,否则执行时权限失败 - 加密触发器无法导出定义,只能靠文档或源码管理记录其逻辑——这点最容易被忽略,等上线后发现功能异常才返工











