如何自动获取SQL Server对象创建脚本(DDL事件、PowerShell)
我需要导出SQL Server数据库中所有对象的完整创建脚本(包含表、约束、索引等,和SSMS手动生成的效果一致),用于保存初始版本以便回滚,同时配合DDL事件记录修改历史。之前用Object_Definition()只能获取部分对象,无法覆盖表定义等内容,于是改用PowerShell+SMO的脚本,但运行时出现以下错误:
Could not load file or assembly 'Microsoft.SqlServer.Dmf.Common, Version=13.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.
仅在SSMS 18的C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE路径下找到Version=16.100.0.0版本的该DLL,求解决思路。
解决思路
1. 使用官方SqlServer PowerShell模块(推荐)
手动加载SMO组件极易出现版本不匹配问题,微软官方提供了SqlServer模块,可通过NuGet安装,自动处理依赖:
- 以管理员身份打开PowerShell,执行以下命令安装模块:
Install-PackageProvider -Name NuGet -Force Install-Module -Name SqlServer -Force
- 修改原脚本的加载逻辑,替换为:
Import-Module SqlServer
模块会自动加载对应版本的SMO组件,彻底避免版本冲突。
2. 手动指定现有DLL路径加载
如果不想使用模块,可直接指定已找到的16.100.0.0版本DLL路径加载,替换原脚本的LoadWithPartialName行:
$smoIdePath = "C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE" Add-Type -Path "$smoIdePath\Microsoft.SqlServer.Dmf.Common.dll" Add-Type -Path "$smoIdePath\Microsoft.SqlServer.SMO.dll" Add-Type -Path "$smoIdePath\Microsoft.SqlServer.SmoExtended.dll" Add-Type -Path "$smoIdePath\Microsoft.SqlServer.ConnectionInfo.dll"
注意要加载所有相关依赖DLL,避免遗漏。
3. 优化脚本获取全量对象
原脚本仅处理了表,若要导出所有用户对象(视图、存储过程、函数等),可扩展对象收集逻辑:
$targetDb = $s.Databases[$DB] $allObjects = @() # 收集用户表(排除系统表) $allObjects += $targetDb.Tables | Where-Object { !$_.IsSystemObject } # 收集用户视图 $allObjects += $targetDb.Views | Where-Object { !$_.IsSystemObject } # 收集用户存储过程 $allObjects += $targetDb.StoredProcedures | Where-Object { !$_.IsSystemObject } # 收集用户定义函数 $allObjects += $targetDb.UserDefinedFunctions | Where-Object { !$_.IsSystemObject } # 收集用户触发器 $allObjects += $targetDb.Triggers | Where-Object { !$_.IsSystemObject } # 生成脚本 $scrp.Script($allObjects)
同时优化Scripter选项,确保脚本包含所有必要元素:
$scrp.Options.AppendToFile = $true $scrp.Options.ClusteredIndexes = $true $scrp.Options.DriAll = $true $scrp.Options.ScriptDrops = $false $scrp.Options.IncludeHeaders = $true $scrp.Options.ToFileOnly = $true $scrp.Options.Indexes = $true $scrp.Options.WithDependencies = $true $scrp.Options.ScriptBatchTerminator = $true # 添加GO分隔符,方便后续执行脚本 $scrp.Options.FileName = $logFile
内容的提问来源于stack exchange,提问作者Vssmm

