Jak znaleźć wszystkie tabele w bazie danych, które nie mają wyraźnego klucza podstawowego?

10

Wyszukiwarka Google ujawniła miliony trafień dotyczących wyszukiwania tabel bez indeksowania klastrowego, przy czym PK zwykle jest indeksem klastrowym tabeli. Jednak tabela może łatwo mieć naturalny klucz jako indeks klastrowany i nieklastrowy indeks zastępczy, jak kolumna tożsamości.

Jak znaleźć wszystkie tabele w bazie danych bez zdefiniowanego klucza podstawowego? Mam w tej bazie danych 245 tabel: kontrola manualna jest rażąco nieefektywna.

ProfK
źródło

Odpowiedzi:

13

Kilka sposobów na skórowanie tego kota, ale działa to dobrze w SQL Server 2005 i nowszych, i uważam, że jest to bezbolesny sposób na rozwiązanie problemu -

OBJECTPROPERTY()Funkcji można wymienić różne właściwości o obiektach - podobnie jak tabele. Jedną z tych właściwości jest to, czy tabela ma klucz podstawowy.

OBJECTPROPERTY(object_id, tablehasprimarykey) = 0 byłoby tabelą bez klucza podstawowego.

Więc

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

Powinien dać ci to, czego potrzebujesz. Możesz dowiedzieć się wszystkiego o innych sposobach używania funkcji OBJECTPROPERTY () w książkach online. To jest wersja 2012 artykułu.

Mike Walsh
źródło
no cóż, obiekt_id będzie działał. Myślałem, że używamy funkcji. ale sys.tablessam daje identyfikator i dziękuję za pokazanie tej cudownej funkcji.
Biju jose
Nie ma problemu. To dobra funkcja. Wiele nieruchomości. W tym przypadku masz rację - sys.tables już zawiera w sobie identyfikator_obiektu. i to jest object_id, który chcemy przekazać dla parametru ID do funkcji OBJECTPROPERTY. Dzięki za dobry haczyk dla zarezerwowanego słowa kluczowego, którego tam użyłem :)
Mike Walsh,
, miałeś dokładnie rację co do funkcji object_id, właśnie tam pomieszałem. cóż, dziękuję za wskazanie tego. cóż, objectproperty()jest dostępny od 2005 roku, właśnie sprawdziłem bol, prawda?
Biju jose
Tak. Tam w latach 2005 - 2014 i później :-)
Mike Walsh,
Zredagowałem skrypt, aby dodać nazwę schematu. Zauważ, że (podobnie jak OBJECTPROPERTY) funkcja OBJECT_SCHEMA_NAME () była nowością w MSSQL 2005.
Greenstone Walker
5

Rozwiązanie Mike'a doskonale nadaje się do konkretnego problemu.

Jeśli chcesz więcej elastyczności, oto alternatywa, która może być łatwo przekształcił kwerendę, która zwraca inne informacje, takie jak znalezienie wszystkich tabel, które są hałdy, lub znalezienie tabel, które nie mają unikalne ograniczeń w ogóle .

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

Gdy twój (pod) system przejdzie ponad ~ 50 tabel, bardzo ważne jest zapoznanie się ze wszystkimi tabelami metadanych, ponieważ, jak powiedziałeś, ręczne przeglądanie każdej tabeli jest niepraktyczne (i podatne na błędy!).

Jon Seigel
źródło
+1 za „ponieważ, jak powiedziałeś, ręczne przeglądanie każdej tabeli jest niepraktyczne (i podatne na błędy!”). Amen tam. Bardzo podatny na błędy :)
Mike Walsh,
4

Funkcja zarządzania zasadami w SQL Server może to zrobić.

Aspekt tabeli zawiera pola @HasIndex i @HasClusteredIndex (a także inne, które mogą być przydatne, np. Wyzwalacze). Można utworzyć zasadę sprawdzającą warunki na wszystkich tabelach, we wszystkich bazach danych, na wielu serwerach (przy użyciu funkcji Central Management Server).

Nie może jednak sprawdzić istnienia indeksu klucza podstawowego lub ograniczenia. Przysiągłbym, że istnieje pole @HasPrimaryKey, ale nie ma go w MSSQL2012. Albo źle pamiętam, albo wariuję.

Uwaga: Zarządzanie zasadami jest dołączone do wersji SQL Server 2012 Enterprise, Business Intelligence i Standard. Nie jest dostępny w wersji Express.

Greenstone Walker
źródło
2
Myślę, że możesz napisać niestandardowy warunek, który to sprawdza. +1 za zupełnie inny sposób na zrobienie tego.
Jon Seigel