จะค้นหาการพึ่งพาคีย์ต่างประเทศใน SQL Server ได้อย่างไร


163

ฉันจะค้นหาการพึ่งพาคีย์ต่างประเทศทั้งหมดในคอลัมน์ใดคอลัมน์หนึ่งได้อย่างไร

อะไรคือทางเลือกที่แตกต่างกัน (กราฟิกใน SSMS, แบบสอบถาม / มุมมองใน SQL Server, เครื่องมือฐานข้อมูลบุคคลที่สาม, รหัสใน. NET)

คำตอบ:


290

แบบสอบถามต่อไปนี้จะช่วยให้คุณเริ่มต้นได้ มันแสดงรายการความสัมพันธ์ของกุญแจต่างประเทศทั้งหมดในฐานข้อมูลปัจจุบัน

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

คุณยังสามารถดูความสัมพันธ์แบบกราฟิกภายในสตูดิโอการจัดการเซิร์ฟเวอร์ SQL ภายในไดอะแกรมฐานข้อมูล


8
ขอบคุณ! ฉันต้องการเพิ่ม << WHERE FK.TABLE_NAME = 'MyTable' AND CU.COLUMN_NAME = 'MyColumn' >> เพื่อรับคอลัมน์เฉพาะ
แม้ Mien

1
+1! และหากต้องการรับคอลัมน์เฉพาะ แต่สำหรับทุกตาราง "WHERE CU.COLUMN_NAME = 'MyColumn'" จะทำเช่นนั้น
เหลียง

1
คล้ายกับ Even - ฉันใช้ WHERE PK.TABLE_NAME = 'MyTable' เพื่อค้นหาตารางที่ขึ้นอยู่กับ
Lanceomagnifico

7
@samkitshah: ไม่มีใครพูดว่ามันจะ คำถามถูกติดแท็ก sql-server ซึ่งโดยนิยามคือเทคโนโลยีของ Microsoft Postgres ไม่เกี่ยวข้องกับมัน
Neolisk

2
-1: แบบสอบถามนี้คิดถึงคีย์ต่างประเทศที่ได้รับการสนับสนุนโดยข้อ จำกัด ที่ไม่ซ้ำกันหรือดัชนีที่ไม่ซ้ำกันแทนที่จะเป็นคีย์หลักในตารางที่อ้างอิง ต่อMSDN :“ ข้อ จำกัด กุญแจต่างประเทศไม่จำเป็นต้องเชื่อมโยงกับข้อ จำกัด ของคีย์หลักในตารางอื่น สามารถกำหนดเพื่ออ้างอิงคอลัมน์ของข้อ จำกัด UNIQUE ในตารางอื่นได้” คำตอบสามารถทำงานกับข้อ จำกัด ที่ไม่ซ้ำกันได้โดยการลบการเข้าร่วมครั้งล่าสุดและดัชนีที่ไม่ซ้ำกันโดยการลบการรวมสองครั้งล่าสุด แต่จะ จำกัด ข้อมูลที่ส่งคืน
Douglas

100

ลอง: sp_help [table_name]

คุณจะได้รับข้อมูลทั้งหมดเกี่ยวกับโต๊ะรวมถึงกุญแจต่างประเทศทั้งหมด


2
เป็นคนดีมีประโยชน์มาก น่าจดจำยิ่งกว่าคำตอบที่ทำเครื่องหมายไว้! ไม่สามารถเชื่อว่าคุณไม่สามารถเห็นพวกเขาใน ssms!
JonnyRaa

4
ดีมากขอบคุณ แต่สำหรับการค้นหาของ FK ฉันชอบผลลัพธ์จากคำตอบของ Michael ด้านล่าง: sp_fkeys [table]
AjV Jsy

.... หรือถ้าคุณไม่ได้รับผลลัพธ์จากนั้น (แต่ sp_help แสดงคีย์ต่างประเทศ) เวอร์ชันฟูลเลอร์อาจช่วยได้:sp_fkeys @fktable_name='TableName'
AjV Jsy

ยอดเยี่ยม! สั้นและกระชับ!
zeroflaw

39

หากคุณวางแผนที่จะลบหรือเปลี่ยนชื่อโต๊ะหรือคอลัมน์เพื่อค้นหาการอ้างอิงคีย์ต่างประเทศเท่านั้นอาจไม่เพียงพอ

ตารางอ้างอิงไม่ได้เชื่อมต่อกับ foreign key - คุณจะต้องค้นหาตารางอ้างอิงที่อาจไม่ได้เชื่อมต่อกับ foreign key (ฉันเคยเห็นฐานข้อมูลจำนวนมากที่มีการออกแบบไม่ดีที่ไม่ได้กำหนด foreign key แต่มีข้อมูลที่เกี่ยวข้อง ) วิธีแก้ไขอาจเป็นการค้นหาชื่อคอลัมน์ในตารางทั้งหมดและค้นหาคอลัมน์ที่คล้ายกัน

วัตถุฐานข้อมูลอื่น ๆ - นี่อาจเป็นเรื่องเล็กน้อย แต่ถ้าคุณกำลังมองหาการอ้างอิงทั้งหมดนอกจากนี้ยังเป็นสิ่งสำคัญในการตรวจสอบวัตถุที่ต้องพึ่งพา

เครื่องมือ GUI - ลองใช้ตัวเลือก SSMS“ ค้นหาวัตถุที่เกี่ยวข้อง” หรือเครื่องมือต่าง ๆ เช่นApexSQL Search (เครื่องมือฟรีรวมเข้ากับ SSMS) เพื่อระบุวัตถุที่ต้องพึ่งพาทั้งหมดรวมถึงตารางที่เชื่อมต่อกับ foreign key


39

เนื่องจากคำถามของคุณมุ่งเน้นไปที่ตารางเดียวคุณสามารถใช้สิ่งนี้:

EXEC sp_fkeys 'TableName'

ฉันพบมันดังนั้นที่นี่:

https://stackoverflow.com/a/12956348/652519

ฉันพบข้อมูลที่ฉันต้องการอย่างรวดเร็ว โดยจะแสดงรายการตารางคอลัมน์และชื่อของคีย์ต่างประเทศ

แก้ไข

นี่คือลิงค์ไปยังเอกสารประกอบที่ให้รายละเอียดพารามิเตอร์ต่าง ๆ ที่สามารถใช้ได้: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-fkeys-transact-sql


29

ฉันคิดว่าสคริปต์นี้ราคาไม่แพง:

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

หนึ่งที่ผมชอบที่จะใช้เรียกว่า SQL พึ่งพาการติดตามโดยเกตซอฟท์แวแดง คุณสามารถใส่วัตถุฐานข้อมูลใด ๆ เช่นตารางกระบวนงานที่เก็บไว้และจากนั้นมันจะวาดเส้นความสัมพันธ์ระหว่างวัตถุอื่น ๆ ทั้งหมดที่ขึ้นอยู่กับรายการที่คุณเลือก

ให้การแสดงกราฟิกที่ดีมากของการอ้างอิงในสคีมาของคุณ


2
นอกจากนี้ยังเป็นเครื่องมือที่ยอดเยี่ยมในการแสดงบุคคลที่ไม่ใช่ด้านเทคนิคซึ่งพวกเขาจำเป็นต้องใช้เงินในการปรับโครงสร้างการออกแบบฐานข้อมูลใหม่ก่อนที่จะล้มลง กราฟที่สร้างขึ้นนั้นค่อนข้างน่าสนใจ
27432 Rob Allen อัลเลน

1
Rob: ฉันชอบโหลด schema ฐานข้อมูลทั้งหมดในนั้นแล้วเปลี่ยนระหว่างเค้าโครงที่แตกต่างกันเพียงเพื่อให้ฉันสามารถดูทุกสิ่งที่บินไปรอบ ๆ
TheTXI

4

ขอบคุณมากกับจอห์นสันสมคำค้นหาของเขายอดเยี่ยมมาก!

นอกจากนี้: คุณควรเพิ่ม "และ PT.ORDINAL_POSITION = CU.ORDINAL_POSITION" ที่ท้ายแบบสอบถามของคุณ

หากคุณมีหลายฟิลด์ในคีย์หลักคำสั่งนี้จะจับคู่ฟิลด์ที่สอดคล้องกัน (ฉันมีกรณีแบบสอบถามของคุณสร้างชุดค่าผสมทั้งหมดดังนั้นสำหรับ 2 ฟิลด์ในคีย์หลักฉันมีผลลัพธ์ 4 รายการสำหรับคีย์ต่างประเทศที่เกี่ยวข้อง) .

(ขออภัยฉันไม่สามารถแสดงความคิดเห็นคำตอบของ John ได้เนื่องจากฉันมีคะแนนชื่อเสียงไม่เพียงพอ)


3

แบบสอบถามนี้จะส่งกลับรายละเอียดเกี่ยวกับกุญแจต่างประเทศในตารางรองรับหลายคอลัมน์

    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

หลังจากค้นหามานานฉันพบวิธีแก้ปัญหาที่ใช้งานได้ ฐานข้อมูลของฉันไม่ใช้ sys.foreign_key_columns และ information_schema.key_column_usage มีคีย์หลักเท่านั้น

ฉันใช้ SQL Server 2015

การแก้ไข 1 (ไม่ค่อยได้ใช้)

หากวิธีการอื่นไม่ได้ผลก็จะทำงานได้ดี:

        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

โซลูชัน 2 (ใช้กันทั่วไป)

ในกรณีส่วนใหญ่สิ่งนี้จะใช้ได้ดี:

        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

คุณสามารถใช้ INFORMATION_SCHEMA.KEY_COLUMN_USAGE และ sys.foreign_key_columns เพื่อรับข้อมูลเมตาของคีย์ต่างประเทศสำหรับตารางเช่นชื่อข้อ จำกัด ตารางอ้างอิงและคอลัมน์อ้างอิงเป็นต้น

ด้านล่างคือแบบสอบถาม:

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

หากค้นหาการพึ่งพาคีย์ต่างประเทศฉันคิดว่าประโยค PT ควรอยู่ที่:

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

และเงื่อนไขON :

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

ตามปกติแล้วจะใช้คีย์หลักของตารางต่างประเทศฉันคิดว่าปัญหานี้ไม่เคยถูกสังเกตมาก่อน


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

มันจะทำให้คุณ:

FK นั้นเป็น Schema ที่ FK เป็นเจ้าของ

  • "ตารางอ้างอิง" หรือตารางที่มี FK
  • "คอลัมน์อ้างอิง" หรือคอลัมน์ภายในตารางอ้างอิงที่ชี้ไปที่ FK
  • "ตารางอ้างอิง" หรือตารางที่มีคอลัมน์คีย์ที่ FK ของคุณชี้ไป
  • "คอลัมน์อ้างอิง" หรือคอลัมน์ที่เป็นกุญแจสำคัญที่ FK ของคุณชี้ไป

-1

ใช้ข้อมูล information_chema;

SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.