导出视图脚本必须用“Script View as → CREATE To”,禁用“DROP and CREATE To”以防生产环境误删;需确认高级设置中“Script DROP and CREATE”为False、“Script USE DATABASE”为True,并注意WITH ENCRYPTION、跨库引用、EXECUTE AS权限及ORDER BY兼容性问题。

导出视图脚本时必须用 Script as CREATE To,不能选 Script as DROP and CREATE To
SQL Server Management Studio(SSMS)右键视图 → “Script View as” 默认是 CREATE To,但很多人误点成 DROP and CREATE To。在目标库已有同名视图时,后者会先执行 DROP VIEW,一旦中间出错(比如权限不足、依赖未就绪),视图就丢了,且无法回滚——生产环境极危险。
批量操作前务必确认 SSMS 的“高级脚本设置”中:Script DROP and CREATE 设为 False;Script USE DATABASE 设为 True(避免脚本里漏掉 USE [db_name] 导致建到 master)。
- 如果视图含
WITH ENCRYPTION或SCHEMABINDING,导出脚本会自动保留,但目标库需有对应权限才能执行 - 加密视图无法被反向工程,但导出脚本本身仍是明文的
CREATE VIEW ... WITH ENCRYPTION,执行后才生效 - 若源库视图引用了跨库对象(如
[OtherDB].[dbo].[Table]),脚本里会带完整三段式名称,目标库必须存在同名数据库和权限,否则执行失败
用 PowerShell 批量导出比 SSMS GUI 更稳,关键要控制 BatchSize 和 IncludeDependencies
SSMS 一次选几百个视图右键导出,容易卡死或漏项。改用 sqlpackage.exe 或 PowerShell + SMO 更可靠。推荐 PowerShell 脚本,因为可逐个捕获错误并记录:
Get-SqlDatabase -ServerInstance "PROD-SRV" -DatabaseName "MyDB" |
ForEach-Object {
$_.Views | Where-Object Name -in $viewList |
ForEach-Object {
$script = $_.Script(@("IncludeHeaders", "IncludeIfNotExists"))
$script | Out-File ".\$($_.Name).sql" -Encoding UTF8
}
}
注意两点:一是 @("IncludeHeaders", "IncludeIfNotExists") 让脚本能安全重跑(加 IF NOT EXISTS 判断);二是别开 IncludeDependencies——视图依赖表/函数通常已存在,开它会把整张表也导出来,彻底乱套。
- 若视图定义里用了
SELECT *,迁移后需手动验证列顺序/类型是否兼容,尤其下游 ETL 或报表工具对列序敏感 - PowerShell 中
Get-SqlDatabase需提前安装SqlServer模块(Install-Module SqlServer -Scope CurrentUser) - 导出路径建议用绝对路径,相对路径在定时任务中容易因工作目录变化而写错位置
CREATE VIEW 脚本在目标库执行失败?优先查 EXECUTE AS 和架构权限
常见报错是 Cannot find the object "xxx" because it does not exist or you do not have permissions,表面看是对象不存在,实际多因权限问题。特别是源视图用了 EXECUTE AS OWNER 或 EXECUTE AS 'user',目标库该用户可能不存在,或 OWNER 对应的 schema_authorizer 未映射。
解决方法不是删掉 EXECUTE AS,而是先在目标库创建对应用户,并确保其对所引用对象有 SELECT 权限:
- 运行
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('dbo.MyView')查原定义,确认是否有EXECUTE AS - 若存在,目标库需执行
CREATE USER [same_login] FOR LOGIN [same_login],再GRANT SELECT ON [ref_table] TO [same_login] - 不建议用
EXECUTE AS CALLER替代——它把权限检查推迟到调用时,上线后可能突然报错,排查成本更高
视图含 ORDER BY 且没配 TOP 或 OFFSET?脚本能导出但执行必报错
SQL Server 不允许在视图定义中单独写 ORDER BY(除非搭配 TOP (100) PERCENT 或 OFFSET 0 ROWS)。很多旧视图靠 TOP 2147483647 硬凑,导出脚本里会原样保留。但这类写法在 SQL Server 2012+ 已被标记为“不推荐”,且在某些兼容级别下直接拒绝执行。
迁移前必须扫描所有视图定义:
SELECT name, definition FROM sys.views v JOIN sys.sql_modules m ON v.object_id = m.object_id WHERE definition LIKE '%ORDER BY%' AND definition NOT LIKE '%TOP %' AND definition NOT LIKE '%OFFSET%'
- 发现即改:补
TOP (99.999999) PERCENT(不推荐)或重构逻辑,把排序移到查询端 - 用
OFFSET 0 ROWS最干净,但要求兼容级别 ≥ 110(SQL Server 2012) - 千万别信“现在能跑就不用动”——这类视图在 AG 只读副本、某些 BI 工具直连场景下会直接失败
definition 里的隐式假设。批量迁移前花十分钟跑一遍依赖校验和 ORDER BY 扫描,比上线后半夜救火强得多。

















