Fala pessoal!
Tudo tranquilo, né ?

Hoje vou mostrar a vocês como executar uma query em todos os databases de uma instância SQL Server. Muitas vezes isso é útil para criação de rotinas de monitoramento de espaço, rodar um checkdb em todos os bancos e muitas outras necessidades do dia-a-dia.

Para realizar essa atividade existem várias formas diferentes de programar, mas vou abordar duas das mais utilizadas

sp_MSforeachdb
A procedure sp_MSforeachdb já vem por padrão no SQL Server, mas não possui documentação oficial pela Microsoft até o momento e por isso, muita gente não sabe da sua existência ou como utilizá-la. Um dos detalhes mais importantes em sua utilização, é o wildcart ?, que irá receber o nome do database que está sendo iterado pela Stored Procedure sp_MSforeachdb.

Vamos a um exemplo bem básico que vai apenas exibir o nome de cada database:

EXEC master.sys.sp_MSforeachdb '
USE [?]

SELECT DB_NAME()'

Exibindo os datafiles de cada database

EXEC master.sys.sp_MSforeachdb 'SELECT * FROM [?].sys.database_files'

Exibindo os datafiles de cada database que contenha a palavra “Cobranca”

EXEC master.sys.sp_MSforeachdb '
IF (''[?]'' LIKE ''%Cobranca%'')
    SELECT * FROM [?].sys.database_files
'

Exibindo o nome dos databases, schemas e tabelas que começam com Cliente na sua instância

EXEC master.sys.sp_MSforeachdb '
USE [?];

IF((SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''Cliente'') > 0)
BEGIN
    SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ''Cliente%''
END'

Utilizando views de catálogo do SQL Server
A procedure de sistema sp_MSforeachdb é muito útil no dia-a-dia do DBA e bem fácil de ser utilizada, mas já vi alguns casos onde o banco ignoraalguns databases durante a iteração quando há uma sobrecarga muito grande no servidor. Por isso, vou mostrar uma outra abordagem para atender essa necessidade.

Exemplo 1:

IF (OBJECT_ID('tempdb..#Databases') IS NOT NULL) DROP TABLE #Databases
SELECT [name], [dbid], IDENTITY(INT, 1, 1) AS Ordem
INTO #Databases
FROM sys.sysdatabases	WITH(NOLOCK)
ORDER BY name


DECLARE
    @Qt_Databases INT = (SELECT COUNT(*) FROM #Databases),
    @Contador INT = 1,
    @Ds_Database SYSNAME,
    @Ds_Query VARCHAR(MAX) = 'SELECT * FROM sys.database_files',
    @Cmd VARCHAR(MAX)

	
WHILE(@Contador <= @Qt_Databases)
BEGIN
		
    SELECT @Ds_Database = name
    FROM #Databases
    WHERE Ordem = @Contador

    SET @Cmd = 'USE [' + @Ds_Database + ']; ' + CHAR(10) + @Ds_Query
    EXEC(@Cmd)
        
    SET @Contador = @Contador + 1

END

Exemplo 2:
Após criar a SP abaixo, retorna o nome de todos os databases e os grava numa tabela temporária

IF (OBJECT_ID('tempdb..#Dbs') IS NOT NULL) DROP TABLE #Dbs
CREATE TABLE #Dbs (
    Nome SYSNAME
)

INSERT INTO #Dbs
EXEC dbo.stpExecuta_Query_Databases
    @Ds_Query = 'SELECT DB_NAME()'

Retorna o nome de todos os databases que contenham “Cobranca” no nome

EXEC dbo.stpExecuta_Query_Databases
	@Ds_Query = 'SELECT DB_NAME()',
	@Ds_Incluir_Database = '%Cobranca%'

Retorna o nome de todos os databases que NÃO contenham “Cobranca” no nome

EXEC dbo.stpExecuta_Query_Databases
	@Ds_Query = 'SELECT DB_NAME()',
	@Ds_Excluir_Database = '%Cobranca%'

Código da Stored Procedure stpExecuta_Query_Databases:

CREATE PROCEDURE dbo.stpExecuta_Query_Databases (
    @Ds_Query VARCHAR(MAX),
    @Ds_Incluir_Database VARCHAR(MAX) = NULL,
    @Ds_Excluir_Database VARCHAR(MAX) = NULL
)
AS BEGIN

    IF (OBJECT_ID('tempdb..#Databases') IS NOT NULL) DROP TABLE #Databases
    CREATE TABLE #Databases (
        [name] SYSNAME,
        [database_id] INT,
        [Ordem] INT IDENTITY(1, 1)
    )

    IF (@Ds_Incluir_Database IS NULL AND @Ds_Excluir_Database IS NULL)
    BEGIN

        INSERT INTO #Databases
        SELECT [name], [database_id]
        FROM sys.databases	WITH(NOLOCK)
        WHERE state_desc = 'ONLINE'
        ORDER BY name

    END
    ELSE BEGIN
        
        IF (@Ds_Incluir_Database IS NOT NULL)
        BEGIN

            INSERT INTO #Databases
            SELECT [name], [database_id]
            FROM sys.databases	WITH(NOLOCK)
            WHERE [name] LIKE (@Ds_Incluir_Database)
            AND state_desc = 'ONLINE'
            ORDER BY name

        END
        ELSE BEGIN

            INSERT INTO #Databases
            SELECT [name], [database_id]
            FROM sys.databases	WITH(NOLOCK)
            WHERE [name] NOT LIKE (@Ds_Excluir_Database)
            AND state_desc = 'ONLINE'
            ORDER BY name

        END

    END	


    DECLARE
        @Qt_Databases INT = (SELECT COUNT(*) FROM #Databases),
        @Contador INT = 1,
        @Ds_Database SYSNAME,
        @Cmd VARCHAR(MAX)


    WHILE(@Contador <= @Qt_Databases)
    BEGIN
        
        SELECT @Ds_Database = name
        FROM #Databases
        WHERE Ordem = @Contador

        SET @Cmd = 'USE [' + @Ds_Database + ']; ' + CHAR(10) + @Ds_Query
        EXEC(@Cmd)
        
        SET @Contador = @Contador + 1

    END


END