Como localizo todas as tabelas em um banco de dados que não possuem chave primária explícita?

10

Uma pesquisa no Google divulgou milhões de ocorrências sobre como encontrar tabelas sem indexação em cluster, o PK normalmente sendo o índice em cluster de uma tabela. No entanto, uma tabela pode facilmente ter uma chave natural como índice clusterizado e um índice substituto não clusterizado, como uma coluna de identidade.

Como localizo todas as tabelas em um banco de dados sem uma chave primária definida? Eu tenho 245 tabelas neste banco de dados: a inspeção manual é extremamente ineficiente.

ProfK
fonte

Respostas:

13

Existem algumas maneiras de esfolar esse gato, mas isso funciona bem no SQL Server 2005 e posterior, e acho que é uma maneira fácil de resolver o problema -

A OBJECTPROPERTY()função pode listar várias propriedades sobre objetos - como tabelas. Uma dessas propriedades é se uma tabela possui ou não uma chave primária.

OBJECTPROPERTY(object_id, tablehasprimarykey) = 0 seria uma tabela sem uma chave primária.

então

SELECT OBJECT_SCHEMA_NAME( object_id ) as SchemaName, name AS TableName
FROM sys.tables
WHERE OBJECTPROPERTY(object_id,'tablehasprimaryKey') = 0 
ORDER BY SchemaName, TableName ;

Deve dar o que você precisa. Você pode ver tudo sobre as outras maneiras de usar a função OBJECTPROPERTY () nos livros online. Esta é a versão 2012 do artigo.

Mike Walsh
fonte
bem, o object_id funcionará. Pensei que estivéssemos usando a sys.tablesfunção.
Biju jose
Sem problemas. É uma boa função ter. Muitas propriedades. Nesse caso, você está certo - sys.tables já lista o object_id dentro dele. e esse é o object_id que queremos passar para o parâmetro ID para a função OBJECTPROPERTY. Obrigado pela boa captura da palavra-chave reservada que usei lá :) #
Mike Walsh
, você estava precisamente correto sobre a função object_id, eu apenas misturei as coisas lá em cima objectproperty().
Biju jose
Sim. Há em 2005 - 2014 e mais além neste momento :-)
Mike Walsh
Editei o script para adicionar o nome do esquema. Note-se que (como OBJECTPROPERTY) a função OBJECT_SCHEMA_NAME () era novo para MSSQL 2005.
Greenstone Walker
5

A solução de Mike é excelente para o problema específico.

Se você quiser mais flexibilidade, aqui está uma alternativa que pode ser facilmente transformado em uma consulta que retorna outras informações, tais como encontrar todas as tabelas que são montes, ou encontrar tabelas que não têm restrições exclusivas em tudo .

SELECT
    OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName,
    t.name AS TableName
    FROM sys.tables t
    WHERE
        NOT EXISTS
        (
            SELECT *
                FROM sys.indexes i
                WHERE
                    (i.object_id = t.object_id) AND
                    (i.is_primary_key = 1)
        );

Quando seu (sub) sistema ultrapassar ~ 50 tabelas, é realmente importante se familiarizar com todas as tabelas de metadados, porque, como você disse, passar por cada tabela manualmente é impraticável (e propenso a erros!).

Jon Seigel
fonte
+1 em "porque, como você disse, passar por cada tabela manualmente é impraticável (e propenso a erros!)". Amém lá. Muito propenso a erros :)
Mike Walsh
4

O recurso de gerenciamento de políticas do SQL Server pode fazer isso.

A faceta da tabela possui os campos @HasIndex e @HasClusteredIndex (além de outros que podem ser úteis, como gatilhos). Uma política pode ser criada para verificar as condições em todas as tabelas, em todos os bancos de dados, em vários servidores (usando o recurso Central Management Server).

No entanto, ele não pode verificar a existência de um índice ou restrição de chave primária. Eu juraria que havia um campo @HasPrimaryKey, mas não existe no MSSQL2012. Estou me lembrando errado ou ficando louco.

Nota: O Policy Management está incluído nas edições SQL Server 2012 Enterprise, Business Intelligence e Standard. Não está disponível na edição Express.

Andarilho de Pedra Verde
fonte
2
Eu acho que você poderia escrever uma condição personalizada que verifica isso. +1 para uma maneira totalmente diferente de fazer isso.
precisa