Prompt: Crie um comando para listar as tabelas do meu banco de dados que possuam uma chave primária composta por mais de um campo.
Com certeza. Essa é uma consulta de metadados muito útil para a análise e documentação de um banco de dados.
Para obter essa informação, precisamos consultar as tabelas de sistema do Firebird, que armazenam toda a estrutura do banco (o DDL). A lógica é contar quantos campos (segments) existem para cada constraint do tipo PRIMARY KEY. Se a contagem for maior que 1, trata-se de uma chave primária composta.
Aqui está o comando SQL, pronto para ser executado em qualquer ferramenta de acesso ao Firebird.
Comando para Listar Chaves Primárias Compostas
SELECT
rc.RDB$RELATION_NAME AS NOME_DA_TABELA,
rc.RDB$CONSTRAINT_NAME AS NOME_DA_CONSTRAINT,
COUNT(seg.RDB$FIELD_NAME) AS TOTAL_DE_CAMPOS,
LIST(TRIM(seg.RDB$FIELD_NAME), ', ') AS CAMPOS_DA_CHAVE
FROM
RDB$RELATION_CONSTRAINTS rc
JOIN
RDB$INDEX_SEGMENTS seg ON rc.RDB$INDEX_NAME = seg.RDB$INDEX_NAME
WHERE
rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
AND rc.RDB$RELATION_NAME NOT STARTING WITH 'RDB$' -- Ignora tabelas de sistema
AND rc.RDB$RELATION_NAME NOT STARTING WITH 'MON$' -- Ignora tabelas de monitoramento
GROUP BY
rc.RDB$RELATION_NAME,
rc.RDB$CONSTRAINT_NAME
HAVING
COUNT(seg.RDB$FIELD_NAME) > 1
ORDER BY
rc.RDB$RELATION_NAME;
Como o Comando Funciona (Passo a Passo)
FROM RDB$RELATION_CONSTRAINTS rc: Começamos pela tabela que armazena todas as constraints (regras) das tabelas, como chaves primárias, estrangeiras, etc.JOIN RDB$INDEX_SEGMENTS seg ...: Unimos com a tabelaRDB$INDEX_SEGMENTS. Toda chave primária no Firebird é implementada através de um índice único. Esta tabela detalha quais colunas (RDB$FIELD_NAME) compõem cada índice (RDB$INDEX_NAME).WHERE rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY': Filtramos para obter apenas as constraints que são chaves primárias.AND rc.RDB$RELATION_NAME NOT STARTING WITH ...: Adicionamos um filtro para ignorar as tabelas internas do próprio Firebird, mostrando apenas as tabelas criadas pelo usuário.GROUP BY rc.RDB$RELATION_NAME, rc.RDB$CONSTRAINT_NAME: Agrupamos os resultados por tabela e por nome da constraint. Isso nos permite contar os campos para cada chave primária individualmente.HAVING COUNT(seg.RDB$FIELD_NAME) > 1: Esta é a lógica principal. Após agrupar, a cláusulaHAVINGfiltra os grupos, mantendo apenas aqueles onde a contagem de campos (COUNT) é maior que 1.SELECT ...: Finalmente, selecionamos as informações úteis para exibição:NOME_DA_TABELA: O nome da tabela que possui a chave composta.NOME_DA_CONSTRAINT: O nome da constraint da chave primária.TOTAL_DE_CAMPOS: A contagem de campos que compõem a chave.CAMPOS_DA_CHAVE: Uma lista legível, separada por vírgulas, de todas as colunas que formam a chave primária.
Insight de DBA
Encontrar chaves primárias compostas é muito comum em:
- Tabelas Associativas (ou de Ligação): Em um relacionamento N-para-N (muitos-para-muitos), a tabela que liga as duas outras geralmente tem uma chave primária composta pelas chaves estrangeiras de ambas. Exemplo: Tabela
ALUNO_DISCIPLINAcom a PK (ID_ALUNO,ID_DISCIPLINA). - Tabelas de Histórico ou Log: Onde a identidade de um registro é definida por uma entidade e uma data/hora. Exemplo: Tabela
HISTORICO_PRECO_PRODUTOcom a PK (ID_PRODUTO,DATA_VIGENCIA).
Esta consulta é uma excelente ferramenta para auditoria e documentação do seu modelo de dados.
