|

Obtendo a Quantidade de Registros em Todas as Tabelas de um Banco de Dados

Compartilhe :

Uma forma de descobrir quantos registros existem em cada tabela do banco é percorrer a lista de tabelas do banco e rodar um COUNT(*) em cada uma delas. O script abaixo faz isso usando um cursor, percorrendo a information_schema.tables e executando uma contagem para cada tabela encontrada.

Se você está procurando uma forma rápida de identificar apenas as maiores tabelas do banco, sem contar linha por linha, veja o post sobre identificando as maiores tabelas do seu banco, que resolve isso direto pelas views de sistema, sem precisar rodar COUNT(*) em cada tabela.

O script com cursor

DECLARE @NomeDaTabela VARCHAR(128);

DECLARE meu_cursor CURSOR FOR
    SELECT TABLE_NAME
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_TYPE = 'BASE TABLE';

OPEN meu_cursor;
FETCH NEXT FROM meu_cursor INTO @NomeDaTabela;

WHILE @@FETCH_STATUS = 0
BEGIN
    EXECUTE (
        'SELECT ''' + @NomeDaTabela + ''' AS Tabela, COUNT(*) AS [Total de Registros] FROM ' + QUOTENAME(@NomeDaTabela)
    );
    FETCH NEXT FROM meu_cursor INTO @NomeDaTabela;
END;

CLOSE meu_cursor;
DEALLOCATE meu_cursor;

Repare no uso de QUOTENAME(@NomeDaTabela) no FROM do SQL dinâmico: isso protege o comando contra nomes de tabela com espaços, caracteres especiais ou que coincidam com palavras reservadas do SQL Server, cercando o nome com colchetes automaticamente.

Um cuidado com bancos que têm mais de um schema

O script busca apenas pelo nome da tabela (TABLE_NAME), sem considerar o schema (TABLE_SCHEMA). Se o seu banco tiver tabelas com o mesmo nome em schemas diferentes (por exemplo, vendas.Pedidos e arquivo.Pedidos), o script original pode contar a tabela errada ou falhar. Para evitar isso, inclua o schema também:

DECLARE @NomeDaTabela VARCHAR(128);
DECLARE @Schema VARCHAR(128);

DECLARE meu_cursor CURSOR FOR
    SELECT TABLE_SCHEMA, TABLE_NAME
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_TYPE = 'BASE TABLE';

OPEN meu_cursor;
FETCH NEXT FROM meu_cursor INTO @Schema, @NomeDaTabela;

WHILE @@FETCH_STATUS = 0
BEGIN
    EXECUTE (
        'SELECT ''' + @Schema + '.' + @NomeDaTabela + ''' AS Tabela, COUNT(*) AS [Total de Registros] FROM '
        + QUOTENAME(@Schema) + '.' + QUOTENAME(@NomeDaTabela)
    );
    FETCH NEXT FROM meu_cursor INTO @Schema, @NomeDaTabela;
END;

CLOSE meu_cursor;
DEALLOCATE meu_cursor;

Por que essa abordagem pode ser lenta

Esse script faz um COUNT(*) de verdade, tabela por tabela, o que garante uma contagem exata no momento da execução. O custo é que, em bancos com tabelas muito grandes, cada COUNT(*) precisa ler a tabela inteira (ou o índice mais compacto disponível), o que pode deixar o script lento em bancos grandes com muitas tabelas.

Se o objetivo é apenas ter uma ideia do tamanho das tabelas, sem precisar de uma contagem exata em tempo real, o SQL Server já mantém essa informação pronta nas views de sistema sys.partitions, sem precisar percorrer tabela por tabela. Veja o post sobre identificando as maiores tabelas do seu banco para essa alternativa, muito mais rápida em bases grandes.

Alternativa sem cursor: um único resultado, ao invés de vários

Um efeito colateral do script com cursor é que cada EXECUTE gera um resultado separado, um por tabela. Se você preferir um único resultado consolidado, é possível montar dinamicamente uma consulta com UNION ALL, usando STRING_AGG (disponível desde o SQL Server 2017) para juntar tudo em um só comando:

DECLARE @SQL NVARCHAR(MAX);

SELECT @SQL = STRING_AGG(
    'SELECT ''' + TABLE_SCHEMA + '.' + TABLE_NAME + ''' AS Tabela, COUNT(*) AS [Total de Registros] FROM '
    + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME),
    ' UNION ALL '
)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE';

EXEC (@SQL);

Essa versão continua fazendo um COUNT(*) por tabela (o custo de leitura é o mesmo), mas devolve tudo em um único resultado, mais fácil de visualizar e exportar.

Conclusão

O script com cursor é uma forma direta de obter a contagem exata de registros de todas as tabelas do banco, e vale reforçar o QUOTENAME para lidar com nomes de tabela fora do padrão. Para bancos muito grandes, onde rodar COUNT(*) em cada tabela fica caro, considere a alternativa via sys.partitions, que entrega uma estimativa quase instantânea sem precisar ler os dados.

Posts Similares