SQL Server'da yabancı anahtar bağımlılıkları nasıl bulunur?


163

Belirli bir sütundaki tüm yabancı anahtar bağımlılıklarını nasıl bulabilirim?

Farklı alternatifler nelerdir (SSMS'de grafik olarak, SQL Server'da sorgular / görünümler, 3. taraf veritabanı araçları, .NET'te kod)?

Yanıtlar:


290

Aşağıdaki sorgu başlamanıza yardımcı olacaktır. Geçerli veritabanındaki tüm Yabancı Anahtar İlişkilerini listeler.

SELECT
    FK_Table = FK.TABLE_NAME,
    FK_Column = CU.COLUMN_NAME,
    PK_Table = PK.TABLE_NAME,
    PK_Column = PT.COLUMN_NAME,
    Constraint_Name = C.CONSTRAINT_NAME
FROM
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
    ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
    ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
    ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
            SELECT
                i1.TABLE_NAME,
                i2.COLUMN_NAME
            FROM
                INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
            INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
                ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
            WHERE
                i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
           ) PT
    ON PT.TABLE_NAME = PK.TABLE_NAME

İlişkileri, Grafik Diyagramları içindeki SQL Server Management stüdyosunda grafiksel olarak da görüntüleyebilirsiniz.


8
Teşekkürler! Belirli bir sütunu almak için << WHERE FK.TABLE_NAME = 'MyTable' VE CU.COLUMN_NAME = 'MyColumn' >> eklemem gerekiyordu.
Hatta Mien

1
1! Ve belirli bir sütunu almak için gerekirse, ancak tüm tablolar için, "WHERE CU.COLUMN_NAME = 'Sütunum'" işe yarar.
liang

1
Even'e benzer - bağlı tabloyu bulmak için WHERE PK.TABLE_NAME = 'MyTable' kullandım.
Lanceomagnifico

7
@samkitshah: Kimse olacağını söylemedi. Soru, tanımı gereği Microsoft teknolojisi olan sql-server olarak etiketlenmiştir. Postgres'in bununla hiçbir ilgisi yok.
Neolisk

2
-1: Bu sorgu, başvurulan tabloda birincil anahtar yerine benzersiz bir kısıtlama veya benzersiz bir dizin tarafından desteklenen yabancı anahtarları özlüyor. MSDN başına : “Yabancı anahtar kısıtlamasının yalnızca başka bir tablodaki birincil anahtar kısıtlamasına bağlanması gerekmez; başka bir tabloda UNIQUE sınırlamasının sütunlarına başvuruda bulunmak için de tanımlanabilir. ” Yanıt, son birleştirmeyi kaldırarak benzersiz kısıtlamalarla ve son iki birleştirmeyi kaldırarak benzersiz dizinlerle çalışmak için yanıtlanabilir, ancak bu, döndürülen bilgileri kısıtlar.
Douglas

100

Deneyin: sp_help [table_name]

tüm yabancı anahtarlar da dahil olmak üzere tablo hakkında tüm bilgileri alacaksınız


2
güzel, çok yararlı. İşaretli cevaptan daha unutulmaz! onları sadece ssms'de göremeyeceğinize inanamıyorum!
JonnyRaa

4
Çok hoş teşekkürler. Ama FK adlı arayan için, aşağıda Michael'ın cevabını çıkış tercih sp_fkeys [table]
AJV Jsy

.... veya bundan sonuç alamazsanız (ancak sp_help yabancı anahtarları gösterir), daha dolgun sürüm yardımcı olabilir:sp_fkeys @fktable_name='TableName'
AjV Jsy

süper! kısa ve özlü!
zeroflaw

39

Bir tabloyu veya sütunu silmeyi veya yeniden adlandırmayı planlıyorsanız, yalnızca yabancı anahtar bağımlılıkları bulmak yeterli olmayabilir.

Yabancı anahtarla bağlı olmayan referans tabloları - Ayrıca , yabancı anahtarla bağlanamayan referans tablolarını da aramanız gerekir (Yabancı anahtarlar tanımlanmamış, ancak ilgili veriler içeren kötü tasarımlı birçok veritabanı gördüm. ). Çözüm, tüm tablolarda sütun adı aramak ve benzer sütunları aramak olabilir.

Diğer veritabanı nesneleri - bu muhtemelen biraz konu dışıdır, ancak tüm referansları arıyorsanız, bağımlı nesneleri kontrol etmek de önemlidir.

GUI Araçları - Yabancı anahtarla bağlı tablolar da dahil olmak üzere tüm bağımlı nesneleri tanımlamak için SSMS “İlgili nesneleri bul” seçeneğini veya ApexSQL Arama (ücretsiz araç, SSMS'ye entegre) gibi araçları deneyin .



29

Bu komut dosyasının daha ucuz olduğunu düşünüyorum:

SELECT f.name AS ForeignKey, OBJECT_NAME(f.parent_object_id) AS TableName,
    COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
    OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
    COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id

6

Gerçekten kullanmak istediğim bir tanesi Red Gate Software tarafından SQL Bağımlılık İzleyicisi . Tablolar, saklı yordamlar vb. Gibi herhangi bir veritabanı nesnesini / nesnelerini koyabilirsiniz ve daha sonra otomatik olarak seçtiğiniz öğelere dayanan diğer tüm nesneler arasındaki ilişki çizgilerini çizecektir.

Şemanızdaki bağımlılıkların çok iyi bir grafik temsilini verir.


2
Ayrıca teknik olmayan insanlara, veritabanı tasarımlarını yeniden gözden geçirmek için biraz para harcamaları gerektiğini göstermek için harika bir araçtır. Oluşturduğu grafikler oldukça ilgi çekicidir.
Rob Allen

1
Rob: Orada tüm bir veritabanı şemasını yüklemeyi ve sonra farklı mizanpajlar arasında geçiş yapmayı seviyorum.
TheTXI

4

John Sansom'a çok teşekkürler, sorgusu müthiş!

Ayrıca: sorgunuzun sonuna "AND PT.ORDINAL_POSITION = CU.ORDINAL_POSITION" eklemeniz gerekir.

Birincil anahtarda birden fazla alanınız varsa, bu ifade karşılık gelen alanları birbiriyle eşleştirecektir (durumum vardı, sorgunuz tüm kombinasyonları oluşturdu, bu nedenle birincil anahtardaki 2 alan için karşılık gelen yabancı anahtar için 4 sonuç aldım) .

(Üzgünüm John'un cevabını yorumlayamam çünkü yeterince itibar puanım yok).


3

Bu sorgu bir tablodaki yabancı anahtarlarla ilgili ayrıntıları döndürür, birden çok sütun anahtarını destekler.

    SELECT *
    FROM
    (
    SELECT 
    T1.constraint_name ConstraintName,
    T2.COLUMN_NAME ColumnName,
    T3.TABLE_NAME RefTableName, 
    T3.COLUMN_NAME RefColumnName,
    T1.MATCH_OPTION MatchOption, 
    T1.UPDATE_RULE UpdateRule, 
    T1.DELETE_RULE DeleteRule
    FROM 
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS T1
    INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE T2 
    ON T1.CONSTRAINT_NAME = T2.CONSTRAINT_NAME
    INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE T3 
    ON T1.UNIQUE_CONSTRAINT_NAME = T3.CONSTRAINT_NAME 
    AND T2.ORDINAL_POSITION = T3.ORDINAL_POSITION) A
    WHERE A.ConstraintName = 'table_name'

3

Uzun aramalardan sonra çalışan bir çözüm buldum. Veritabanım sys.foreign_key_columns kullanmıyor ve information_schema.key_column_usage yalnızca birincil anahtarlar içeriyor.

SQL Server 2015 kullanıyorum

ÇÖZÜM 1 (nadiren kullanılır)

Diğer çözümler işe yaramazsa, bu iyi çalışır:

        WITH CTE AS
        (
            SELECT 
                TAB.schema_id,
                TAB.name,
                COL.name AS COLNAME,
                COl.is_identity
            FROM 
                sys.tables TAB INNER JOIN sys.columns COL 
                    ON TAB.object_id = COL.object_id
        )
        SELECT 
            DB_NAME() AS [Database], 
            SCHEMA_NAME(Child.schema_id) AS 'Schema',
            Child.name AS 'ChildTable',
            Child.COLNAME AS 'ChildColumn',
            Parent.name AS 'ParentTable',
            Parent.COLNAME AS 'ParentColumn'
        FROM 
            cte Child INNER JOIN CTE Parent
                ON 
                    Child.COLNAME=Parent.COLNAME AND 
                    Child.name<>Parent.name AND 
                    Child.is_identity+1=Parent.is_identity

ÇÖZÜM 2 (yaygın olarak kullanılır)

Çoğu durumda bu işe yarayacaktır:

        SELECT
            DB_NAME() AS [Database], 
            SCHEMA_NAME(fk.schema_id) AS 'Schema',
            fk.name 'Name',
            tp.name 'ParentTable',
            cp.name 'ParentColumn',
            cp.column_id,
            tr.name 'ChildTable',
            cr.name 'ChildColumn',
            cr.column_id
        FROM
            sys.foreign_keys fk
        INNER JOIN
            sys.tables tp ON fk.parent_object_id = tp.object_id
        INNER JOIN
            sys.tables tr ON fk.referenced_object_id = tr.object_id
        INNER JOIN
            sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
        INNER JOIN
            sys.columns cp ON fkc.parent_column_id = cp.column_id AND fkc.parent_object_id = cp.object_id
        INNER JOIN
            sys.columns cr ON fkc.referenced_column_id = cr.column_id AND fkc.referenced_object_id = cr.object_id
        WHERE 
            -- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tp.name, '.', cp.name) LIKE '%my_table_name%' OR
            -- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tr.name, '.', cr.name) LIKE '%my_table_name%' 
        ORDER BY
            tp.name, cp.column_id

2

Bir tablonun yabancı anahtar meta verisini almak için BİLGİ_SCHEMA.KEY_COLUMN_USAGE ve sys.foreign_key_columns komutlarını kullanabilirsiniz, yani Kısıtlama adı, Referans tablosu ve Referans sütunu vb.

Sorgu aşağıdadır:

SELECT  CONSTRAINT_NAME, COLUMN_NAME, ParentTableName, RefTableName,RefColName FROM 
    (SELECT CONSTRAINT_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = '<tableName>') constraint_details
    INNER JOIN  
    (SELECT ParentTableName, RefTableName,name ,COL_NAME(fc.referenced_object_id,fc.referenced_column_id) RefColName  FROM (SELECT object_name(parent_object_id) ParentTableName,object_name(referenced_object_id) RefTableName,name,OBJECT_ID  FROM sys.foreign_keys WHERE parent_object_id = object_id('<tableName>') ) f 
    INNER JOIN   
    sys.foreign_key_columns AS fc  ON  f.OBJECT_ID = fc.constraint_object_id ) foreign_key_detail 
    on foreign_key_detail.name = constraint_details.CONSTRAINT_NAME

1

@ "John Sansom" cevabı için bir not,

Eğer yabancı anahtar bağımlılıkları aranır, ben PT fıkra Nerede olması gerektiğini düşünüyorum:

i1.CONSTRAINT_TYPE = 'FOREIGN KEY'  -- instead of 'PRIMARY KEY'

ve AÇIK durumu:

ON PT.TABLE_NAME = FK.TABLE_NAME  instead of PK.TABLE_NAME

Yabancı tablonun birincil anahtarı yaygın olarak kullanıldığından, bu konunun daha önce fark edilmediğini düşünüyorum.


0
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

Size verecek:

FK'nin kendisi FK'nin ait olduğu şema

  • "Referans tablosu" veya FK içeren tablo
  • "Referans sütun" veya referans tablosunun içinde FK işaret eden sütun
  • "Referans verilen tablo" veya FK'nizin işaret ettiği anahtar sütunu içeren tablo
  • "Referans verilen sütun" veya FK'nizin işaret ettiği anahtar olan sütun

-1

USE bilgi_kema;

SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.