如何编写通用SQL遍历服务器所有数据库批量执行自定义查询?
跨数据库通用遍历查询实现方案
核心思路是将数据库遍历逻辑和业务查询逻辑拆分,业务查询作为可配置的模板变量,后续更换查询需求时只需修改模板内容,无需调整遍历框架。
通用实现代码
-- ########## 配置区:仅修改此处即可适配不同查询需求 ########## DECLARE @QueryTemplate NVARCHAR(MAX) = N' -- 此处写入单库查询逻辑即可,模板变量说明: -- {{DB_NAME}}:当前遍历的数据库名(字符串格式,可直接作为字段值输出) -- {{DB_QUOTED}}:转义后的数据库名(用于拼接数据库对象路径,自动处理特殊字符) SELECT ''{{DB_NAME}}'' AS DatabaseName, ''guest'' AS Database_User, [permission_name], [state_desc] FROM {{DB_QUOTED}}.sys.database_permissions WHERE [grantee_principal_id] = {{DB_QUOTED}}.sys.DATABASE_PRINCIPAL_ID(''guest'') AND [state_desc] LIKE ''GRANT%'' AND [permission_name] = ''CONNECT'' ' -- 存储查询结果的临时表,字段结构和查询结果对应即可 DECLARE @Result TABLE ( DatabaseName SYSNAME, Database_User SYSNAME, permission_name SYSNAME, state_desc NVARCHAR(60) ) -- ########## 通用遍历逻辑:无需修改 ########## DECLARE @DBName SYSNAME, @ExecSQL NVARCHAR(MAX) DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM master.sys.databases WHERE name NOT IN ('master', 'tempdb', 'msdb') AND state = 0 -- 仅查询在线数据库 AND is_read_only = 0 -- 可选:排除只读数据库 OPEN db_cursor FETCH NEXT FROM db_cursor INTO @DBName WHILE @@FETCH_STATUS = 0 BEGIN SET @ExecSQL = REPLACE(REPLACE(@QueryTemplate, '{{DB_NAME}}', @DBName), '{{DB_QUOTED}}', QUOTENAME(@DBName)) INSERT INTO @Result EXEC sp_executesql @ExecSQL FETCH NEXT FROM db_cursor INTO @DBName END CLOSE db_cursor DEALLOCATE db_cursor -- 输出统一的查询结果 SELECT * FROM @Result
复用说明
- 更换查询需求时,只需修改
@QueryTemplate内的单库查询逻辑,同步调整@Result表的字段结构即可 - 模板中使用双单引号转义,符合SQL动态语句的常规写法要求
- 可根据需求调整数据库过滤条件,比如增加按数据库名前缀过滤、包含指定系统库等逻辑
- 若不需要统一汇总结果,可删除
@Result相关逻辑,直接执行EXEC sp_executesql @ExecSQL即可,每个库会返回独立的结果集
可选封装方案
如果需要高频使用,可封装为系统存储过程,将查询模板和过滤条件作为参数传入,调用时只需传入业务查询语句即可直接执行:
CREATE PROCEDURE dbo.sp_RunQueryOnAllUserDB @QueryTemplate NVARCHAR(MAX), @ExcludeSystemDB BIT = 1 AS BEGIN SET NOCOUNT ON -- 内部遍历逻辑和上述通用逻辑一致,根据参数调整数据库过滤条件即可 END
内容的提问来源于stack exchange,提问作者kriker
相关产品推荐
相关产品推荐

