默认不包含存储过程,因SSMS生成脚本向导默认仅处理表、视图等基础对象,程序性对象需手动展开“程序性→存储过程”并勾选;即使选择“整个数据库”,仍须显式勾选存储过程节点,否则导出结果无CREATE PROCEDURE语句。

直接在数据库节点上右键选“生成脚本”,默认不会包含存储过程——必须手动勾选,否则导出结果里连一个 CREATE PROCEDURE 都没有。
为什么在数据库根节点右键容易漏掉存储过程
SSMS 的“生成脚本”向导默认只处理表、视图、用户定义类型等基础对象,程序性 类对象(如存储过程、函数、触发器)需要显式开启。即使你勾选了“编写整个数据库及所有数据库对象的脚本”,它仍会跳过存储过程,除非你在“选择对象”页面主动展开并勾选“存储过程”节点。
常见错误现象:
– 导出的 SQL 文件里只有 CREATE TABLE,没有一个 CREATE PROCEDURE
– 向导最后一步显示“已处理 0 个存储过程”
– 执行脚本后目标库缺少关键业务逻辑
- 务必展开“程序性”→“存储过程”,逐个勾选,或直接勾选父节点(但注意:部分版本 SSMS 对父节点批量勾选支持不稳定)
- 如果数据库里有上百个存储过程,建议先用 T-SQL 检查数量:
SELECT COUNT(*) FROM sys.procedures WHERE is_ms_shipped = 0,导出后也用这个语句核对目标库是否一致 - 勾选时留意 schema 前缀——比如
[dbo].[usp_GetOrder]和[sales].[usp_GetOrder]是两个不同对象,别只盯着名字漏掉非 dbo 的
高级设置里必须改的三项
点“高级”按钮后,以下三个选项不调整,导出的脚本大概率无法直接执行:
-
要编写的脚本的数据类型:设为仅限架构(存储过程本身不含数据,选“架构和数据”无意义,还可能报错) -
包括 IF NOT EXISTS:建议启用,避免在已有同名存储过程的库中执行时报错 -
脚本主键/外键/索引:关掉。存储过程定义里不需要这些,开了反而混入无关 DDL,增大文件体积且易引发语法错误
其他可选但推荐关闭的项:脚本统计信息、脚本完整文本(后者会影响长存储过程的换行和注释格式)。
导出后脚本执行失败的典型原因
即使脚本生成成功,复制到另一台服务器执行时仍可能报错,主要卡在依赖和权限上:
- 存储过程中引用了自定义函数或视图,但这些对象没一起导出 → 执行时报
Invalid object name - 过程里用了
EXECUTE AS OWNER或WITH ENCRYPTION,而目标库未启用对应安全上下文 → 报权限错误或解密失败 - 脚本开头缺
USE [YourDB],导致在错误数据库上下文中执行 → 报Could not find stored procedure - 过程体里含 Windows 路径或服务器名硬编码(如
\fileservershare),迁移后路径不可达 → 运行时报 IO 错误
建议导出前先跑一遍依赖检查:SELECT referencing_entity_name, referencing_id FROM sys.dm_exec_dependencies WHERE referenced_entity_name IN (SELECT name FROM sys.procedures),确认是否需一并导出被引用对象。
替代方案:用 T-SQL 批量拼接更可控
当 SSMS 图形界面反复失败,或者你需要把每个存储过程单独存成文件时,T-SQL 更可靠:
SELECT 'GO' + CHAR(13) + CHAR(10) + ISNULL(OBJECT_DEFINITION(object_id), '') + CHAR(13) + CHAR(10) FROM sys.procedures WHERE is_ms_shipped = 0 ORDER BY name
这段代码输出的是带 GO 分隔符的完整定义,能绕过 SSMS 对特殊字符(如单引号嵌套、注释块)的转义 bug。注意:OBJECT_DEFINITION() 返回 nvarchar(max),若过程超长,SSMS 结果网格可能截断,建议用“将结果另存为”而非“复制结果”。
真正麻烦的从来不是怎么导出来,而是导出后有没有人去验证每个 CREATE PROCEDURE 是否真能在目标环境里编译通过——尤其跨版本迁移时,2016 不支持的 STRING_AGG 函数如果被写进过程体,脚本会直接挂住。


















