如何在多台SQL Server服务器/数据库中检查sp_Blitz/sp_WhoIsActive版本?
我经常帮团队处理这类批量检查SQL Server扩展存储过程的需求,结合你用SSMS注册服务器组的场景,给你分享两个可靠的方法,亲测好用:
批量检查注册服务器中的sp_Blitz和sp_WhoIsActive
方法1:SSMS多服务器查询直接执行SQL脚本
这是最直接的方式,利用SSMS的「多服务器查询」能力一次性覆盖所有注册服务器。
操作步骤:右键你的注册服务器组 → 选择新建查询,然后执行下面的脚本:
-- 批量检查sp_Blitz和sp_WhoIsActive的存在性与版本 SELECT @@SERVERNAME AS ServerName, 'sp_Blitz' AS ProcedureName, -- 判断存储过程是否存在(覆盖master、DBA等常见存放库) CASE WHEN EXISTS ( SELECT 1 FROM sys.procedures p JOIN sys.schemas s ON p.schema_id = s.schema_id WHERE p.name = 'sp_Blitz' AND s.name = 'dbo' AND DB_NAME() IN ('master', 'DBA', 'Admin') -- 这里可以加你环境里的自定义库 ) THEN '存在' ELSE '不存在' END AS ExistsStatus, -- 获取sp_Blitz版本(依赖扩展属性,大部分版本都支持) CASE WHEN EXISTS ( SELECT 1 FROM sys.procedures p JOIN sys.schemas s ON p.schema_id = s.schema_id WHERE p.name = 'sp_Blitz' AND s.name = 'dbo' AND DB_NAME() IN ('master', 'DBA', 'Admin') ) THEN ( SELECT TOP 1 value FROM sys.extended_properties ep JOIN sys.procedures p ON ep.major_id = p.object_id WHERE p.name = 'sp_Blitz' AND ep.name = 'Version' ) ELSE 'N/A' END AS Version UNION ALL -- 检查sp_WhoIsActive SELECT @@SERVERNAME AS ServerName, 'sp_WhoIsActive' AS ProcedureName, CASE WHEN EXISTS ( SELECT 1 FROM sys.procedures p JOIN sys.schemas s ON p.schema_id = s.schema_id WHERE p.name = 'sp_WhoIsActive' AND s.name = 'dbo' AND DB_NAME() IN ('master', 'DBA', 'Admin') ) THEN '存在' ELSE '不存在' END AS ExistsStatus, -- sp_WhoIsActive支持直接返回版本值 CASE WHEN EXISTS ( SELECT 1 FROM sys.procedures p JOIN sys.schemas s ON p.schema_id = s.schema_id WHERE p.name = 'sp_WhoIsActive' AND s.name = 'dbo' AND DB_NAME() IN ('master', 'DBA', 'Admin') ) THEN ( DECLARE @Version NVARCHAR(100); EXEC @Version = sp_WhoIsActive @Version = 1; SELECT @Version ) ELSE 'N/A' END AS Version ORDER BY ServerName, ProcedureName;
注意事项:
- 如果你的团队把这些存储过程放在其他自定义数据库里,记得修改脚本里的
DB_NAME() IN (...)部分,把对应的库加进去。 - 执行时如果个别服务器报错“找不到存储过程”,要么是脚本没覆盖对应的库,要么就是该服务器确实没安装,不用慌,看结果里的
ExistsStatus就行。
方法2:PowerShell自动化批量检查(适合导出结果)
如果需要把检查结果导出成文件,或者定期自动执行,用PowerShell结合SqlServer模块更高效:
# 先导入SQL Server模块(没安装的话先跑 Install-Module SqlServer) Import-Module SqlServer # 定义要检查的存储过程和可能的存放库 $targetProcs = @('sp_Blitz', 'sp_WhoIsActive') $targetDBs = @('master', 'DBA', 'Admin') # 获取SSMS里的注册服务器列表(替换成你的组名称) $registeredServers = Get-DbaRegisteredServer -SqlInstance 'localhost' -Group '你的注册服务器组名称' # 遍历所有服务器执行检查 $checkResults = foreach ($server in $registeredServers) { foreach ($proc in $targetProcs) { foreach ($db in $targetDBs) { try { # 检查存储过程是否存在 $procExists = Invoke-SqlCmd -ServerInstance $server.ServerName -Database $db -Query " SELECT 1 FROM sys.procedures p JOIN sys.schemas s ON p.schema_id = s.schema_id WHERE p.name = '$proc' AND s.name = 'dbo' " -ErrorAction Stop if ($procExists) { # 根据不同存储过程获取版本 if ($proc -eq 'sp_Blitz') { $procVersion = Invoke-SqlCmd -ServerInstance $server.ServerName -Database $db -Query " SELECT value FROM sys.extended_properties ep JOIN sys.procedures p ON ep.major_id = p.object_id WHERE p.name = 'sp_Blitz' AND ep.name = 'Version' " | Select-Object -ExpandProperty value } else { $procVersion = Invoke-SqlCmd -ServerInstance $server.ServerName -Database $db -Query " DECLARE @v NVARCHAR(100); EXEC @v = sp_WhoIsActive @Version = 1; SELECT @v AS Version " | Select-Object -ExpandProperty Version } # 整理结果对象 [PSCustomObject]@{ ServerName = $server.ServerName Database = $db ProcedureName = $proc ExistsStatus = '存在' Version = $procVersion } } } catch { # 捕获数据库不存在或存储过程缺失的情况 [PSCustomObject]@{ ServerName = $server.ServerName Database = $db ProcedureName = $proc ExistsStatus = '不存在' Version = 'N/A' } } } } } # 输出结果到控制台,或者导出CSV $checkResults | Format-Table -AutoSize $checkResults | Export-Csv -Path 'C:\temp\SP_Check_Results.csv' -NoTypeInformation
优势:
- 自动遍历所有可能的数据库,不用手动调整SQL脚本。
- 结果可以导出为CSV,方便后续整理或共享给团队。
- 适配不同身份验证的服务器,加个
-Credential (Get-Credential)参数就能处理Windows/SQL混合认证的场景。
额外小提示
- 有些早期版本的sp_Blitz可能没有用扩展属性存版本,这时候可以尝试执行
EXEC sp_Blitz @VersionCheck=1,它会把版本信息输出到消息窗口,但多服务器查询里看不到,所以优先用脚本里的扩展属性方法更稳妥。 - 如果你的注册服务器组里有SQL Server 2008这类老版本,脚本依然兼容,因为用到的系统视图都是全版本支持的。
内容的提问来源于stack exchange,提问作者Oreo
相关产品推荐
相关产品推荐

