Jak mogę wyświetlić listę wszystkich kluczy obcych odnoszących się do danej tabeli w SQL Server?

736

Muszę usunąć tabelę o dużym odwołaniu w bazie danych SQL Server. Jak mogę uzyskać listę wszystkich ograniczeń klucza obcego, które muszę usunąć, aby upuścić tabelę?

(Preferowane są odpowiedzi SQL zamiast klikania w interfejsie GUI studia zarządzania).

chillitom
źródło
Aby uzyskać pomoc, zobacz temat Wypisywanie wszystkich obcych kluczy tabeli . Aktualizacja : Link nie jest już dostępny, ale odpowiedni SQL został skopiowany jako odpowiedź na powiązane pytanie. Zależności można także wyświetlać za pomocą GUI.
Galwegian

Odpowiedzi:

1126

Nie jestem pewien, dlaczego nikt nie zasugerował, ale używam sp_fkeysdo wyszukiwania kluczy obcych dla danej tabeli:

EXEC sp_fkeys 'TableName'

Możesz także określić schemat:

EXEC sp_fkeys @pktable_name = 'TableName', @pktable_owner = 'dbo'

Bez określenia schematu, że docs podać następujące dane:

Jeśli parametr pktable_owner nie jest określony, zastosowanie mają domyślne reguły widoczności tabeli bazowego DBMS.

W SQL Server, jeśli bieżący użytkownik jest właścicielem tabeli o określonej nazwie, zwracane są kolumny tej tabeli. Jeśli właściciel punktu nie jest określony, a bieżący użytkownik nie jest właścicielem tabeli o podanej nazwie nazwa_punktowa, procedura szuka tabeli o określonej nazwie nazwa_punktowej należącej do właściciela bazy danych. Jeśli taki istnieje, zwracane są kolumny tej tabeli.

Recep
źródło
41
Z jakiegoś powodu to nie działa dla mnie w bazie danych SQL 2008. sp_help pokazuje relacje, ale to polecenie nie.
tbone
21
@tbone: Miałem ten sam problem, który był związany z niepełnym określeniem parametrów. Biorąc pod uwagę tabelę T, należącą do O, w bazie danych D musisz wykonać EXEC sp_fkeys \ @ pktable_name = 'T', \ @ pktable_owner = 'O', \ @ pktable_qualifier = 'D' Spróbuj spojrzeć na wyniki EXEC sp_tables \ @ nazwa_tabeli = „T”, aby dowiedzieć się, jakie powinny być wartości parametrów.
Mads Ravn,
3
@JustinRusso Możesz obejść ten problem, tworząc tabelę, przechowując wynik w tabeli, a następnie wybierając określone kolumny. Sprawdź ten link na przykład :).
John Odom
3
Działa dobrze w SSMS 2014. Dzięki.
AH.
7
Odpowiedź została już udzielona w powyższych komentarzach: ale dla jasności - EXEC sp_fkeys @ nazwa_komputera = N'Department ', @ pktable_owner = N'dbo'; msdn.microsoft.com/en-NZ/library/ms175090.aspx
Tejas Patel
233

Używałbym funkcji Diagramowanie bazy danych w SQL Server Management Studio, ale skoro to wykluczyłeś - zadziałało to dla mnie w SQL Server 2008 (nie mam 2005).

Aby uzyskać listę odsyłających nazw tabel i kolumn ...

select 
    t.name as TableWithForeignKey, 
    fk.constraint_column_id as FK_PartNo, c.
    name as ForeignKeyColumn 
from 
    sys.foreign_key_columns as fk
inner join 
    sys.tables as t on fk.parent_object_id = t.object_id
inner join 
    sys.columns as c on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id
where 
    fk.referenced_object_id = (select object_id 
                               from sys.tables 
                               where name = 'TableOthersForeignKeyInto')
order by 
    TableWithForeignKey, FK_PartNo

Aby uzyskać nazwy ograniczeń klucza obcego

select distinct name from sys.objects where object_id in 
(   select fk.constraint_object_id from sys.foreign_key_columns as fk
    where fk.referenced_object_id = 
        (select object_id from sys.tables where name = 'TableOthersForeignKeyInto')
)
Gishu
źródło
4
świetny, choć użyty referenced_object_id zamiast nadrzędny. wybierz odrębną nazwę z sys.objects gdzie ID_obiektu w (wybierz fk.constraint_object_id z sys.foreign_key_columns jako fk gdzie fk.referenced_object_id = (wybierz ID_obiektu z sys.tables gdzie nazwa = 'tablename'))
chillitom
4
Możesz uzyskać nazwę FK, dodając „object_name (constraint_object_id)” do wyboru pierwszego zapytania.
sam yi
3
Możesz uzyskać identyfikator obiektu ID_obiektu ('TableOthersForeignKeyInto')
IvanH
189

To daje ci:

  • Sam FK
  • Schemat, do którego należy FK
  • Tabela odniesienia ” lub tabela z FK
  • Kolumna odniesienia ” lub kolumna w tabeli odniesienia, która wskazuje na FK
  • Tabela odniesienia ” lub tabela z kolumną klucza, na którą wskazuje Twój FK
  • Kolumna odniesienia ” lub kolumna, która jest kluczem, na który wskazuje Twój FK

Kod poniżej:

SELECT  obj.name AS FK_NAME,
    sch.name AS [schema_name],
    tab1.name AS [table],
    col1.name AS [column],
    tab2.name AS [referenced_table],
    col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
    ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
    ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
    ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
    ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
    ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
    ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
Gustavo Rubio
źródło
13
To najlepsza odpowiedź w moim przekonaniu, jeśli chcesz później odfiltrować wyniki.
Faliorn,
Działa świetnie! Byłoby jeszcze lepiej, jeśli: a) przedrostek wszystkich nazw kolumn „Fk” / „klucz”), b) sufiks wszystkich nazw kolumn „Nazwie”, c) usuń podkreślenia, d) dodaj KeyTableSchemaName, e) dodaj domyślny order by: KeyTableSchemaName, KeyTableName, KeyColumnName, FkTableSchemaName, FkTableName, FkName oraz f) zmień kolejność kolumn na: KeyTableSchemaName, KeyTableName, KeyColumnName, FkTableSchemaName, FkTableName / nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji, nazwa_kolekcji konwencje i d / e dla najbardziej prawdopodobnego użycia (wyszczególnienie zależnych od FK a Table).
Tom
Taka świetna odpowiedź i przydatne zapytanie. Dziękuję
Rich Dominelli
153

Spróbuj tego :

sp_help 'TableName'
BankZ
źródło
2
Fajna metoda pomocnicza, aby wiedzieć, czy eksplorujesz bazę danych ręcznie. Działa także na Azure SQL Server.
Pac0
48

Należy również pamiętać o odniesieniach do innych obiektów.

Jeśli tabela była wysoce przywoływana przez inne tabele, prawdopodobnie jest również przywoływana przez inne obiekty, takie jak widoki, procedury składowane, funkcje i wiele innych.

Naprawdę polecam narzędzie GUI, takie jak okno dialogowe „wyświetlanie zależności” w SSMS lub darmowe narzędzie, takie jak ApexSQL Wyszukaj, ponieważ wyszukiwanie zależności w innych obiektach może być podatne na błędy, jeśli chcesz to robić tylko za pomocą SQL.

Jeśli SQL jest jedyną opcją, możesz spróbować zrobić to w ten sposób.

select O.name as [Object_Name], C.text as [Object_Definition]
from sys.syscomments C
inner join sys.all_objects O ON C.id = O.object_id
where C.text like '%table_name%'
Mspaja
źródło
21

Pierwotne pytanie zadane w celu umieszczenia listy wszystkich kluczy obcych w tabeli z dużym odwołaniem, aby można ją usunąć.

To małe zapytanie zwraca wszystkie polecenia „upuść klucz obcy” potrzebne do upuszczenia wszystkich kluczy obcych do określonej tabeli:

SELECT 
   'ALTER TABLE ['+sch.name+'].['+referencingTable.Name+'] DROP CONSTRAINT ['+foreignKey.name+']' '[DropCommand]'
FROM sys.foreign_key_columns fk
    JOIN sys.tables referencingTable ON fk.parent_object_id = referencingTable.object_id
    JOIN sys.schemas sch ON referencingTable.schema_id = sch.schema_id
    JOIN sys.objects foreignKey ON foreignKey.object_id = fk.constraint_object_id
    JOIN sys.tables referencedTable ON fk.referenced_object_id = referencedTable.object_id
WHERE referencedTable.name = 'MyTableName'

Przykładowe dane wyjściowe:

[DropCommand]
ALTER TABLE [dbo].[OtherTable1] DROP CONSTRAINT [FK_OtherTable1_MyTable]
ALTER TABLE [dbo].[OtherTable2] DROP CONSTRAINT [FK_OtherTable2_MyTable]

Pomiń klauzulę WHERE, aby uzyskać komendy drop dla wszystkich kluczy obcych w bieżącej bazie danych.

JS
źródło
17

Oto kod SQL, którego bym użył.

SELECT 
   f.name AS 'Name of Foreign Key',
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Fieldname',
   OBJECT_NAME(t.object_id) AS 'References Table name',
   COL_NAME(t.object_id,fc.referenced_column_id) AS 'References fieldname',

   'ALTER TABLE [' + OBJECT_NAME(f.parent_object_id) + ']  DROP CONSTRAINT [' + f.name + ']' AS 'Delete foreign key',

   'ALTER TABLE [' + OBJECT_NAME(f.parent_object_id) + ']  WITH NOCHECK ADD CONSTRAINT [' + 
        f.name + '] FOREIGN KEY([' + COL_NAME(fc.parent_object_id,fc.parent_column_id) + ']) REFERENCES ' + 
        '[' + OBJECT_NAME(t.object_id) + '] ([' +
        COL_NAME(t.object_id,fc.referenced_column_id) + '])' AS 'Create foreign key'
    -- , delete_referential_action_desc AS 'UsesCascadeDelete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
AND OBJECT_NAME(t.object_id) = 'Employees'      --  Just show the FKs which reference a particular table
ORDER BY 2

Nie jest to szczególnie wyraźny SQL, więc spójrzmy na przykład.

Załóżmy więc, że chciałem upuścić Employeestabelę w ukochanej Northwindbazie danych Microsoftu , ale SQL Server powiedział mi, że jeden lub więcej kluczy obcych uniemożliwia mi to.

Powyższe polecenie SQL zwróci te wyniki ...

Klucze obce

Pokazuje mi, że istnieją 3 klucze obce, które odnoszą się do Employeestabeli. Innymi słowy, nie wolno mi było usuwać (upuszczać) tej tabeli, dopóki te trzy klucze obce nie zostaną najpierw usunięte.

W wynikach pierwszy wiersz pokazuje, jak następujące ograniczenie klucza obcego zostanie pokazane w wynikach.

ALTER TABLE [dbo].[Employees]  WITH NOCHECK 
ADD CONSTRAINT [FK_Employees_Employees] FOREIGN KEY([ReportsTo])
REFERENCES [dbo].[Employees] ([EmployeeID])

Przedostatnia kolumna pokazuje polecenie SQL, którego musiałbym użyć, aby usunąć jeden z tych kluczy obcych, np .:

ALTER TABLE [Employees] DROP CONSTRAINT [FK_Employees_Employees]

... a prawa kolumna pokazuje SQL, aby go utworzyć ...

ALTER TABLE [Employees] WITH NOCHECK 
ADD CONSTRAINT [FK_Employees_Employees] 
FOREIGN KEY([ReportsTo]) REFERENCES [Employees] ([EmployeeID])

Dzięki wszystkim tym poleceniom masz wszystko, czego potrzebujesz, aby usunąć odpowiednie klucze obce, aby umożliwić usunięcie tabeli, a następnie odtworzenie ich później.

Uff Mam nadzieję że to pomoże.

Mike Gledhill
źródło
Byłoby wyraźniej, gdybyś użył łączenia wewnętrznego i na klauzulach zamiast połączeń krzyżowych. Ale to pomogło nie mniej!
TamusJRoyce,
16
SELECT PKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       PKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O1.SCHEMA_ID)),
       PKTABLE_NAME = CONVERT(SYSNAME,O1.NAME),
       PKCOLUMN_NAME = CONVERT(SYSNAME,C1.NAME),
       FKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       FKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O2.SCHEMA_ID)),
       FKTABLE_NAME = CONVERT(SYSNAME,O2.NAME),
       FKCOLUMN_NAME = CONVERT(SYSNAME,C2.NAME),
       -- Force the column to be non-nullable (see SQL BU 325751)
       --KEY_SEQ             = isnull(convert(smallint,k.constraint_column_id), sysconv(smallint,0)),
       UPDATE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsUpdateCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       DELETE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsDeleteCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       FK_NAME = CONVERT(SYSNAME,OBJECT_NAME(F.OBJECT_ID)),
       PK_NAME = CONVERT(SYSNAME,I.NAME),
       DEFERRABILITY = CONVERT(SMALLINT,7)   -- SQL_NOT_DEFERRABLE
FROM   SYS.ALL_OBJECTS O1,
       SYS.ALL_OBJECTS O2,
       SYS.ALL_COLUMNS C1,
       SYS.ALL_COLUMNS C2,
       SYS.FOREIGN_KEYS F
       INNER JOIN SYS.FOREIGN_KEY_COLUMNS K
         ON (K.CONSTRAINT_OBJECT_ID = F.OBJECT_ID)
       INNER JOIN SYS.INDEXES I
         ON (F.REFERENCED_OBJECT_ID = I.OBJECT_ID
             AND F.KEY_INDEX_ID = I.INDEX_ID)
WHERE  O1.OBJECT_ID = F.REFERENCED_OBJECT_ID
       AND O2.OBJECT_ID = F.PARENT_OBJECT_ID
       AND C1.OBJECT_ID = F.REFERENCED_OBJECT_ID
       AND C2.OBJECT_ID = F.PARENT_OBJECT_ID
       AND C1.COLUMN_ID = K.REFERENCED_COLUMN_ID
       AND C2.COLUMN_ID = K.PARENT_COLUMN_ID
Omu
źródło
15

Najprostszym z nich jest użycie sys.foreign_keys_columns w SQL. W tabeli znajdują się identyfikatory obiektów wszystkich kluczy obcych zapisane w identyfikatorze kolumny z odnośnikiem Identyfikator tabeli z referencją, a także kolumny i tabele z odnośnikami. Ponieważ identyfikator pozostaje stały, wynik będzie wiarygodny dla dalszych modyfikacji schematu, a także tabel.

Pytanie:

SELECT    
OBJECT_NAME(fkeys.constraint_object_id) foreign_key_name
,OBJECT_NAME(fkeys.parent_object_id) referencing_table_name
,COL_NAME(fkeys.parent_object_id, fkeys.parent_column_id) referencing_column_name
,OBJECT_SCHEMA_NAME(fkeys.parent_object_id) referencing_schema_name
,OBJECT_NAME (fkeys.referenced_object_id) referenced_table_name
,COL_NAME(fkeys.referenced_object_id, fkeys.referenced_column_id) 
referenced_column_name
,OBJECT_SCHEMA_NAME(fkeys.referenced_object_id) referenced_schema_name
FROM sys.foreign_key_columns AS fkeys

Możemy również dodać filtr, używając „gdzie”

WHERE OBJECT_NAME(fkeys.parent_object_id) = 'table_name' AND 
OBJECT_SCHEMA_NAME(fkeys.parent_object_id) = 'schema_name'
Garuda Prasad K
źródło
Jest to doskonałe, gdy trzeba usunąć całe konstrukcje / zestawy DB tabel, do których istnieją odniesienia.
Morvael,
12
SELECT
  object_name(parent_object_id),
  object_name(referenced_object_id),
  name 
FROM sys.foreign_keys
WHERE parent_object_id = object_id('Table Name')
Vishal Gajjar
źródło
11

Używam tego skryptu, aby znaleźć wszystkie szczegóły związane z kluczem obcym. Używam INFORMACJE. SCHEMAT. Poniżej znajduje się skrypt SQL:

SELECT 
    ccu.table_name AS SourceTable
    ,ccu.constraint_name AS SourceConstraint
    ,ccu.column_name AS SourceColumn
    ,kcu.table_name AS TargetTable
    ,kcu.column_name AS TargetColumn
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
    INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
        ON ccu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
        ON kcu.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME  
ORDER BY ccu.table_name
Anvesh
źródło
8

Pierwszy

EXEC sp_fkeys 'Table', 'Schema'

Następnie użyj NimbleText, aby zagrać z wynikami

irfandar
źródło
5

Kilka dobrych odpowiedzi powyżej. Ale wolę mieć odpowiedź za pomocą jednego zapytania. Ten fragment kodu pochodzi z sys.sp_helpconstraint (sys proc)

W ten sposób Microsoft sprawdza, czy z tbl są powiązane klucze obce.

--setup variables. Just change 'Customer' to tbl you want
declare @objid int,
    @objname nvarchar(776)
select @objname = 'Customer'    
select @objid = object_id(@objname)

if exists (select * from sys.foreign_keys where referenced_object_id = @objid)
    select 'Table is referenced by foreign key' =
        db_name() + '.'
        + rtrim(schema_name(ObjectProperty(parent_object_id,'schemaid')))
        + '.' + object_name(parent_object_id)
        + ': ' + object_name(object_id)
    from sys.foreign_keys 
    where referenced_object_id = @objid 
    order by 1

Odpowiedź będzie wyglądać następująco: test_db_name.dbo.Konto: FK_Account_Customer

Mark Varnas
źródło
3
To tak jak 4 oddzielne instrukcje zapytań ... robi to skutecznie to samo w jednym poleceniu: select db_name() + '.' + schema_name(ObjectProperty(parent_object_id,'schemaid')) + '.' + object_name(parent_object_id) + ': ' + object_name(object_id) AS "FK Reference" from sys.foreign_keys where referenced_object_id = object_id('Customer')
hajikelist
5
SELECT
OBJECT_NAME(parent_object_id) 'Parent table',
c.NAME 'Parent column name',
OBJECT_NAME(referenced_object_id) 'Referenced table',
cref.NAME 'Referenced column name'
FROM 
sys.foreign_key_columns fkc 
INNER JOIN 
sys.columns c 
   ON fkc.parent_column_id = c.column_id 
      AND fkc.parent_object_id = c.object_id
INNER JOIN 
sys.columns cref 
   ON fkc.referenced_column_id = cref.column_id 
      AND fkc.referenced_object_id = cref.object_id  where   OBJECT_NAME(parent_object_id) = 'tablename'

Jeśli chcesz uzyskać relację klucza obcego we wszystkich tabelach, wyklucz whereklauzulę, zamiast tego wpisz tablenametablename

Skręcać
źródło
4
 SELECT OBJECT_NAME(fk.parent_object_id) as ReferencingTable, 
        OBJECT_NAME(fk.constraint_object_id) as [FKContraint]
  FROM sys.foreign_key_columns as fk
 WHERE fk.referenced_object_id = OBJECT_ID('ReferencedTable', 'U')

Pokazuje to związek tylko wtedy, gdy są ograniczeniami klucza obcego. Moja baza danych najwyraźniej wyprzedza ograniczenie FK. Niektóre wyzwalacze używają tabeli do wymuszania integralności referencyjnej, a czasami nie ma nic oprócz kolumny o podobnej nazwie wskazującej związek (i żadnej integralności referencyjnej w ogóle).

Na szczęście mamy spójną scenę nazewnictwa, więc jestem w stanie znaleźć tabele odwołań i widoki takie jak to:

SELECT OBJECT_NAME(object_id) from sys.columns where name like 'client_id'

Użyłem tego wyboru jako podstawy do wygenerowania skryptu, który robi to, co muszę zrobić na powiązanych tabelach.

Darrel Lee
źródło
3

Pracując nad tym, co zrobił @Gishu, byłem w stanie stworzyć i używać następującego SQL w SQL Server 2005

SELECT t.name AS TableWithForeignKey, fk.constraint_column_id AS FK_PartNo, 
       c.name AS ForeignKeyColumn, o.name AS FK_Name 
  FROM sys.foreign_key_columns AS fk
       INNER JOIN sys.tables AS t ON fk.parent_object_id = t.object_id
       INNER JOIN sys.columns AS c ON fk.parent_object_id = c.object_id 
                                  AND fk.parent_column_id = c.column_id
       INNER JOIN sys.objects AS o ON fk.constraint_object_id = o.object_id
  WHERE fk.referenced_object_id = (SELECT object_id FROM sys.tables 
                                        WHERE name = 'TableOthersForeignKeyInto')
  ORDER BY TableWithForeignKey, FK_PartNo;

Który Wyświetla nazwy tabel, kolumn i kluczy obcych w jednym zapytaniu.

Raystorm
źródło
3

Określ klucze podstawowe i klucze unikatowe dla wszystkich tabel w bazie danych ...

To powinno wymieniać wszystkie ograniczenia, a na końcu możesz umieścić swoje filtry

/* CAST IS DONE , SO THAT OUTPUT INTEXT FILE REMAINS WITH SCREEN LIMIT*/
WITH   ALL_KEYS_IN_TABLE (CONSTRAINT_NAME,CONSTRAINT_TYPE,PARENT_TABLE_NAME,PARENT_COL_NAME,PARENT_COL_NAME_DATA_TYPE,REFERENCE_TABLE_NAME,REFERENCE_COL_NAME) 
AS
(
SELECT  CONSTRAINT_NAME= CAST (PKnUKEY.name AS VARCHAR(30)) ,
        CONSTRAINT_TYPE=CAST (PKnUKEY.type_desc AS VARCHAR(30)) ,
        PARENT_TABLE_NAME=CAST (PKnUTable.name AS VARCHAR(30)) ,
        PARENT_COL_NAME=CAST ( PKnUKEYCol.name AS VARCHAR(30)) ,
        PARENT_COL_NAME_DATA_TYPE=  oParentColDtl.DATA_TYPE,        
        REFERENCE_TABLE_NAME='' ,
        REFERENCE_COL_NAME='' 

FROM sys.key_constraints as PKnUKEY
    INNER JOIN sys.tables as PKnUTable
            ON PKnUTable.object_id = PKnUKEY.parent_object_id
    INNER JOIN sys.index_columns as PKnUColIdx
            ON PKnUColIdx.object_id = PKnUTable.object_id
            AND PKnUColIdx.index_id = PKnUKEY.unique_index_id
    INNER JOIN sys.columns as PKnUKEYCol
            ON PKnUKEYCol.object_id = PKnUTable.object_id
            AND PKnUKEYCol.column_id = PKnUColIdx.column_id
     INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
            ON oParentColDtl.TABLE_NAME=PKnUTable.name
            AND oParentColDtl.COLUMN_NAME=PKnUKEYCol.name
UNION ALL
SELECT  CONSTRAINT_NAME= CAST (oConstraint.name AS VARCHAR(30)) ,
        CONSTRAINT_TYPE='FK',
        PARENT_TABLE_NAME=CAST (oParent.name AS VARCHAR(30)) ,
        PARENT_COL_NAME=CAST ( oParentCol.name AS VARCHAR(30)) ,
        PARENT_COL_NAME_DATA_TYPE= oParentColDtl.DATA_TYPE,     
        REFERENCE_TABLE_NAME=CAST ( oReference.name AS VARCHAR(30)) ,
        REFERENCE_COL_NAME=CAST (oReferenceCol.name AS VARCHAR(30)) 
FROM sys.foreign_key_columns FKC
    INNER JOIN sys.sysobjects oConstraint
            ON FKC.constraint_object_id=oConstraint.id 
    INNER JOIN sys.sysobjects oParent
            ON FKC.parent_object_id=oParent.id
    INNER JOIN sys.all_columns oParentCol
            ON FKC.parent_object_id=oParentCol.object_id /* ID of the object to which this column belongs.*/
            AND FKC.parent_column_id=oParentCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/
    INNER JOIN sys.sysobjects oReference
            ON FKC.referenced_object_id=oReference.id
    INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
            ON oParentColDtl.TABLE_NAME=oParent.name
            AND oParentColDtl.COLUMN_NAME=oParentCol.name
    INNER JOIN sys.all_columns oReferenceCol
            ON FKC.referenced_object_id=oReferenceCol.object_id /* ID of the object to which this column belongs.*/
            AND FKC.referenced_column_id=oReferenceCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/

)

select * from   ALL_KEYS_IN_TABLE
where   
    PARENT_TABLE_NAME  in ('YOUR_TABLE_NAME') 
    or REFERENCE_TABLE_NAME  in ('YOUR_TABLE_NAME')
ORDER BY PARENT_TABLE_NAME,CONSTRAINT_NAME;

W celach informacyjnych przeczytaj - http://blogs.msdn.com/b/sqltips/archive/2005/09/16/469136.aspx

dekdev
źródło
2
Zawiera zbyt wiele informacji na zadane pytanie. Czy możesz podać jakieś wyjaśnienie (i usunąć dodatkowy kod), aby tylko odpowiedzieć na pytanie? Podałeś tę dokładną odpowiedź na dwa różne pytania i każde z nich potrzebuje tylko części tej odpowiedzi.
Andrew Barber
2
Zredagowałem odpowiedź - Określ klucze podstawowe i klucze unikatowe dla wszystkich tabel w bazie danych ... Myślę, że tutaj odpowiedź jest odpowiednia, ponieważ pytanie dotyczy wszystkich odniesień.
dekdev
3

Korzystałem z tego od 2008 roku. Jest podobny do niektórych innych wymienionych rozwiązań, ale nazwy pól są odpowiednio oznaczone, aby obsłużyć sortowanie według wielkości liter (LatBin). Dodatkowo możesz podać jedną nazwę tabeli i pobrać tylko informacje o tej tabeli.

-->>SPECIFY THE DESIRED DB
USE ???
GO

/*********************************************************************************************

    LIST OUT ALL PRIMARY AND FOREIGN KEY CONSTRAINTS IN A DB OR FOR A SPECIFIED TABLE

*********************************************************************************************/
DECLARE @tblName VARCHAR(255) 

/*******************/

    SET @tblName = NULL-->NULL will return all PK/FK constraints for every table in the database

/*******************/

SELECT PKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()), 
       PKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O1.schema_id)), 
       PKTABLE_NAME = CONVERT(SYSNAME,O1.name), 
       PKCOLUMN_NAME = CONVERT(SYSNAME,C1.name), 
       FKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()), 
       FKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O2.schema_id)), 
       FKTABLE_NAME = CONVERT(SYSNAME,O2.name), 
       FKCOLUMN_NAME = CONVERT(SYSNAME,C2.name), 
       -- Force the column to be non-nullable (see SQL BU 325751) 
       KEY_SEQ             = isnull(convert(smallint,K.constraint_column_id),0), 
       UPDATE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.object_id,'CnstIsUpdateCascade')  
                                        WHEN 1 THEN 0 
                                        ELSE 1 
                                      END), 
       DELETE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.object_id,'CnstIsDeleteCascade')  
                                        WHEN 1 THEN 0 
                                        ELSE 1 
                                      END), 
       FK_NAME = CONVERT(SYSNAME,OBJECT_NAME(F.object_id)), 
       PK_NAME = CONVERT(SYSNAME,I.name), 
       DEFERRABILITY = CONVERT(SMALLINT,7)   -- SQL_NOT_DEFERRABLE 
FROM   sys.all_objects O1, 
       sys.all_objects O2, 
       sys.all_columns C1, 
       sys.all_columns C2, 
       sys.foreign_keys F 
       INNER JOIN sys.foreign_key_columns K 
         ON (K.constraint_object_id = F.object_id) 
       INNER JOIN sys.indexes I 
         ON (F.referenced_object_id = I.object_id 
             AND F.key_index_id = I.index_id) 
WHERE  O1.object_id = F.referenced_object_id 
       AND O2.object_id = F.parent_object_id 
       AND C1.object_id = F.referenced_object_id 
       AND C2.object_id = F.parent_object_id 
       AND C1.column_id = K.referenced_column_id
       AND C2.column_id = K.parent_column_id
       AND (   O1.name = @tblName 
            OR O2.name = @tblName
            OR @tblName IS null)
ORDER BY PKTABLE_NAME,FKTABLE_NAME
Steve Mangiameli
źródło
2

Istnieje sposób obliczenia wszystkich obowiązków dla wybranego identyfikatora. Po prostu zmień wartość @dbTableName, wartość @dbRowId i jej typ (jeśli int musisz usunąć '' w linii nr 82 (.. SET @SQL = ..)). Cieszyć się.

DECLARE @dbTableName varchar(max) = 'User'
DECLARE @dbRowId uniqueidentifier = '21d34ecd-c1fd-11e2-8545-002219a42e1c'

DECLARE @FK_ROWCOUNT int
DECLARE @SQL nvarchar(max)

DECLARE @PKTABLE_QUALIFIER sysname
DECLARE @PKTABLE_OWNER sysname
DECLARE @PKTABLE_NAME sysname
DECLARE @PKCOLUMN_NAME sysname
DECLARE @FKTABLE_QUALIFIER sysname
DECLARE @FKTABLE_OWNER sysname
DECLARE @FKTABLE_NAME sysname
DECLARE @FKCOLUMN_NAME sysname
DECLARE @UPDATE_RULE smallint
DECLARE @DELETE_RULE smallint
DECLARE @FK_NAME sysname
DECLARE @PK_NAME sysname
DECLARE @DEFERRABILITY sysname

IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
    DROP TABLE #Temp1;
CREATE TABLE #Temp1 ( 
    PKTABLE_QUALIFIER sysname,
    PKTABLE_OWNER sysname,
    PKTABLE_NAME sysname,
    PKCOLUMN_NAME sysname,
    FKTABLE_QUALIFIER sysname,
    FKTABLE_OWNER sysname,
    FKTABLE_NAME sysname,
    FKCOLUMN_NAME sysname,
    UPDATE_RULE smallint,
    DELETE_RULE smallint,
    FK_NAME sysname,
    PK_NAME sysname,
    DEFERRABILITY sysname,
    FK_ROWCOUNT int
    );
DECLARE FK_Counter_Cursor CURSOR FOR
    SELECT PKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       PKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O1.SCHEMA_ID)),
       PKTABLE_NAME = CONVERT(SYSNAME,O1.NAME),
       PKCOLUMN_NAME = CONVERT(SYSNAME,C1.NAME),
       FKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       FKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O2.SCHEMA_ID)),
       FKTABLE_NAME = CONVERT(SYSNAME,O2.NAME),
       FKCOLUMN_NAME = CONVERT(SYSNAME,C2.NAME),
       -- Force the column to be non-nullable (see SQL BU 325751)
       --KEY_SEQ             = isnull(convert(smallint,k.constraint_column_id), sysconv(smallint,0)),
       UPDATE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsUpdateCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       DELETE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsDeleteCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       FK_NAME = CONVERT(SYSNAME,OBJECT_NAME(F.OBJECT_ID)),
       PK_NAME = CONVERT(SYSNAME,I.NAME),
       DEFERRABILITY = CONVERT(SMALLINT,7)   -- SQL_NOT_DEFERRABLE
    FROM   SYS.ALL_OBJECTS O1,
           SYS.ALL_OBJECTS O2,
           SYS.ALL_COLUMNS C1,
           SYS.ALL_COLUMNS C2,
           SYS.FOREIGN_KEYS F
           INNER JOIN SYS.FOREIGN_KEY_COLUMNS K
             ON (K.CONSTRAINT_OBJECT_ID = F.OBJECT_ID)
           INNER JOIN SYS.INDEXES I
             ON (F.REFERENCED_OBJECT_ID = I.OBJECT_ID
                 AND F.KEY_INDEX_ID = I.INDEX_ID)
    WHERE  O1.OBJECT_ID = F.REFERENCED_OBJECT_ID
           AND O2.OBJECT_ID = F.PARENT_OBJECT_ID
           AND C1.OBJECT_ID = F.REFERENCED_OBJECT_ID
           AND C2.OBJECT_ID = F.PARENT_OBJECT_ID
           AND C1.COLUMN_ID = K.REFERENCED_COLUMN_ID
           AND C2.COLUMN_ID = K.PARENT_COLUMN_ID
           AND O1.NAME = @dbTableName
OPEN FK_Counter_Cursor;
FETCH NEXT FROM FK_Counter_Cursor INTO @PKTABLE_QUALIFIER, @PKTABLE_OWNER, @PKTABLE_NAME, @PKCOLUMN_NAME, @FKTABLE_QUALIFIER, @FKTABLE_OWNER, @FKTABLE_NAME, @FKCOLUMN_NAME, @UPDATE_RULE, @DELETE_RULE, @FK_NAME, @PK_NAME, @DEFERRABILITY;
WHILE @@FETCH_STATUS = 0
   BEGIN
        SET @SQL = 'SELECT @dbCountOut = COUNT(*) FROM [' + @FKTABLE_NAME + '] WHERE [' + @FKCOLUMN_NAME + '] = ''' + CAST(@dbRowId AS varchar(max)) + '''';
        EXECUTE sp_executesql @SQL, N'@dbCountOut int OUTPUT', @dbCountOut = @FK_ROWCOUNT OUTPUT;
        INSERT INTO #Temp1 (PKTABLE_QUALIFIER, PKTABLE_OWNER, PKTABLE_NAME, PKCOLUMN_NAME, FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, FKCOLUMN_NAME, UPDATE_RULE, DELETE_RULE, FK_NAME, PK_NAME, DEFERRABILITY, FK_ROWCOUNT) VALUES (@FKTABLE_QUALIFIER, @PKTABLE_OWNER, @PKTABLE_NAME, @PKCOLUMN_NAME, @FKTABLE_QUALIFIER, @FKTABLE_OWNER, @FKTABLE_NAME, @FKCOLUMN_NAME, @UPDATE_RULE, @DELETE_RULE, @FK_NAME, @PK_NAME, @DEFERRABILITY, @FK_ROWCOUNT)
      FETCH NEXT FROM FK_Counter_Cursor INTO @PKTABLE_QUALIFIER, @PKTABLE_OWNER, @PKTABLE_NAME, @PKCOLUMN_NAME, @FKTABLE_QUALIFIER, @FKTABLE_OWNER, @FKTABLE_NAME, @FKCOLUMN_NAME, @UPDATE_RULE, @DELETE_RULE, @FK_NAME, @PK_NAME, @DEFERRABILITY;
   END;
CLOSE FK_Counter_Cursor;
DEALLOCATE FK_Counter_Cursor;
GO
SELECT * FROM #Temp1
GO
PRZYZNAĆ
źródło
2

Serwer MySQL ma information_schema.REFERENTIAL_CONSTRAINTStabelę FYI, możesz ją filtrować według nazwy tabeli lub nazwy tabeli, do której istnieje odwołanie.

David
źródło
2

Lista wszystkich kluczy obcych odnoszących się do danej tabeli w SQL Server:

Nazwę tabeli referencyjnej i nazwę kolumny można uzyskać, wykonując następujące zapytanie ...

SELECT 
   OBJECT_NAME(f.parent_object_id) TableName,
   COL_NAME(fc.parent_object_id,fc.parent_column_id) ColName
FROM 
   sys.foreign_keys AS f
INNER JOIN 
   sys.foreign_key_columns AS fc 
      ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN 
   sys.tables t 
      ON t.OBJECT_ID = fc.referenced_object_id
WHERE 
   OBJECT_NAME (f.referenced_object_id) = 'TableName'

I poniższy zrzut ekranu do zrozumienia ...

wprowadź opis zdjęcia tutaj

Manish Kumar Gurjar
źródło
1

Otrzymuje dowolny klucz obcy, który dotyczy wybranej tabeli. * Przyjmuje format _FIRSTABLENAME_SECONDTABLENAME.

 declare @tablename as varchar(MAX)
 SET @tablename = 'yourtablename'
 SELECT name
 FROM YOURDATABASE.sys.objects
 WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT' and (name LIKE '%_' + @tablename + 'empdb_%' or name LIKE '%_' + @tablename )

To jest bardziej ogólna forma:

 SELECT name
 FROM YOURDATABASE_PROD.sys.objects
 WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT' and name LIKE '%' + @tablename + '%' and
 name NOT LIKE '[a-zA-Z0-9]' + @tablename + '%' and name NOT LIKE '%' + @tablename + '[a-zA-Z0-9]' 

źródło
1

Następujące rozwiązanie działa dla mnie:

--Eliminar las llaves foraneas
declare @query varchar(8000)
declare cursorRecorrerTabla cursor for

SELECT  'ALTER TABLE [PoaComFinH].['+sch.name+'].['+referencingTable.Name+'] DROP CONSTRAINT ['+foreignKey.name+']' 'query'
FROM PoaComFinH.sys.foreign_key_columns fk
JOIN PoaComFinH.sys.tables referencingTable ON fk.parent_object_id = referencingTable.object_id
JOIN PoaComFinH.sys.schemas sch ON referencingTable.schema_id = sch.schema_id
JOIN PoaComFinH.sys.objects foreignKey ON foreignKey.object_id = fk.constraint_object_id
JOIN PoaComFinH.sys.tables referencedTable ON fk.referenced_object_id = referencedTable.object_id


--3ro. abrir el cursor.
open cursorRecorrerTabla
fetch next from cursorRecorrerTabla
into @query
while @@fetch_status = 0
begin
--inicio cuerpo del cursor
    print @query
    exec(@query)
--fin cuerpo del cursor
fetch next from cursorRecorrerTabla
into @query
end
--cerrar cursor
close cursorRecorrerTabla
deallocate cursorRecorrerTabla
Jorge Santos Neill
źródło
0

Poniżej znajdziesz zapytanie:

 SELECT OBJECT_NAME (FK.referenced_object_id) 'Referenced Table', 
      OBJECT_NAME(FK.parent_object_id) 'Referring Table', FK.name 'Foreign Key', 
      COL_NAME(FK.referenced_object_id, FKC.referenced_column_id) 'Referenced Column',
      COL_NAME(FK.parent_object_id,FKC.parent_column_id) 'Referring Column'
     FROM sys.foreign_keys AS FK
             INNER JOIN sys.foreign_key_columns AS FKC 
                 ON FKC.constraint_object_id = FK.OBJECT_ID
     WHERE OBJECT_NAME (FK.referenced_object_id) = 'YourTableName'
     AND COL_NAME(FK.referenced_object_id, FKC.referenced_column_id) = 'YourColumnName'
     order by  OBJECT_NAME(FK.parent_object_id)
Dilip Oganiya
źródło
0

Spróbuj także.

EXEC sp_fkeys 'tableName', 'schemaName'

z sp_fkeyswas mogą filtrować wyniki, nie tylko pk nazwy tabeli i schematu, ale również z fk nazwy tabeli i schematu. połączyć

Hossein Narimani Rad
źródło
0

Najkorzystniejsza odpowiedź @BankZ

sp_help 'TableName'   

dodatkowo dla innego schematu

sp_help 'schemaName.TableName'   
Knight Fighter
źródło