Как найти все таблицы в БД, которые не имеют явного первичного ключа?

10

Поиски в Google дали миллионы просмотров о том, как найти таблицы без кластеризованной индексации, причем PK обычно является кластерным индексом таблицы. Однако таблица может легко иметь естественный ключ в виде кластеризованного индекса и некластеризованный суррогатный индекс, например столбец идентификаторов.

Как найти все таблицы в БД без определения первичного ключа? У меня есть 245 таблиц в этой БД: ручная проверка крайне неэффективна.

ProfK
источник

Ответы:

13

Несколько способов обшарить эту кошку, но это прекрасно работает в SQL Server 2005 и более поздних версиях, и я нахожу это безболезненным способом решения проблемы

OBJECTPROPERTY()Функция может перечислить различные свойства об объектах - как таблицы. Одним из таких свойств является наличие у таблицы первичного ключа.

OBJECTPROPERTY(object_id, tablehasprimarykey) = 0 будет таблица без первичного ключа.

Так

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

Должен дать вам то, что вам нужно. Вы можете увидеть все о других способах использования функции OBJECTPROPERTY () в книгах онлайн. Это версия статьи 2012 года.

Майк Уолш
источник
хорошо, object_id будет работать, я думал, что мы используем функцию. но sys.tablesсам дает идентификатор и спасибо за показ этой замечательной функции.
Бижу Хосе
Нет проблем. Это хорошая функция, чтобы иметь. Много свойств. В этом случае у вас все правильно - sys.tables уже перечисляет object_id внутри него. и это object_id, который мы хотим передать для параметра ID в функцию OBJECTPROPERTY. Спасибо за хороший улов зарезервированного ключевого слова, которое я использовал там :)
Майк Уолш
, вы были совершенно правы в отношении функции object_id, я просто все перепутал. спасибо за указание на это. хорошо, что objectproperty()доступно с 2005 года, я только что проверил бол, верно?
Бижу Хосе
Да. Там в 2005 - 2014 и далее на данный момент :-)
Майк Уолш
Я отредактировал скрипт для добавления имени схемы. Обратите внимание, что (как и OBJECTPROPERTY) функция OBJECT_SCHEMA_NAME () была новой в MSSQL 2005.
Greenstone Walker
5

Решение Майка отлично подходит для конкретной проблемы.

Если вы хотите больше гибкости, вот альтернатива , которая может быть легко трансформировалась в запрос , который возвращает другую информация, например, найти все таблицы , которые кучи, или найти таблицы , которые не имеют ограничений уникальности на всех .

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)
        );

Когда ваша (подсистема) переходит ~ 50 таблиц, очень важно ознакомиться со всеми таблицами метаданных, потому что, как вы сказали, просмотр каждой таблицы вручную нецелесообразен (и подвержен ошибкам!).

Джон Сайгель
источник
+1 за «потому что, как вы сказали, проходить каждую таблицу вручную непрактично (и подвержено ошибкам!)». Аминь там. Очень подвержен ошибкам :)
Майк Уолш
4

Функция управления политиками SQL Server может сделать это.

Фасет таблицы имеет поля @HasIndex и @HasClusteredIndex (а также другие, которые могут быть полезны, например, триггеры). Можно создать политику для проверки условий во всех таблицах, во всех базах данных на нескольких серверах (с помощью функции центрального сервера управления).

Однако он не может проверить наличие индекса или ограничения первичного ключа. Я бы поклялся, что есть поле @HasPrimaryKey, но его нет в MSSQL2012. Я либо вспоминаю, либо схожу с ума.

Примечание. Управление политиками входит в состав выпусков SQL Server 2012 Enterprise, Business Intelligence и Standard. Это не доступно в Экспресс-выпуске.

Гринстоун Уолкер
источник
2
Я думаю, что вы могли бы написать пользовательское условие, которое проверяет это. +1 за совершенно другой способ сделать это.
Джон Зигель