Làm cách nào để tìm phụ thuộc khóa ngoài trong SQL Server?


163

Làm cách nào tôi có thể tìm thấy tất cả các phụ thuộc khóa ngoại trên một cột cụ thể?

Các lựa chọn thay thế khác nhau (đồ họa trong SSMS, truy vấn / lượt xem trong SQL Server, công cụ cơ sở dữ liệu của bên thứ 3, mã trong .NET) là gì?

Câu trả lời:


290

Các truy vấn sau đây sẽ giúp bạn bắt đầu. Nó liệt kê tất cả các mối quan hệ khóa ngoài trong cơ sở dữ liệu hiện tại.

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

Bạn cũng có thể xem các mối quan hệ bằng đồ họa trong studio Quản lý máy chủ SQL trong Sơ đồ cơ sở dữ liệu.


8
Cảm ơn! Tôi chỉ cần thêm << WHERE FK.TABLE_NAME = 'MyTable' VÀ CU.COLUMN_NAME = 'MyColumn' >> để có được cột cụ thể.
Ngay cả Miên

1
+1! Và nếu cần để lấy cột cụ thể nhưng cho tất cả các bảng, "WHERE CU.COLUMN_NAME = 'MyColumn'" sẽ làm được.
liang

1
Tương tự như Chẵn - Tôi đã sử dụng WHERE PK.TABLE_NAME = 'MyTable' để tìm bảng phụ thuộc vào.
Lanceomagnifico

7
@samkitshah: Không ai nói điều đó. Câu hỏi được gắn thẻ máy chủ sql, theo định nghĩa là công nghệ của Microsoft. Postgres không có gì để làm với nó.
Neolisk

2
-1: Truy vấn này bỏ lỡ các khóa ngoại được hỗ trợ bởi một ràng buộc duy nhất hoặc chỉ mục duy nhất, thay vì một khóa chính, trong bảng được tham chiếu. Mỗi MSDN : Một ràng buộc khóa ngoại không phải được liên kết chỉ với một ràng buộc khóa chính trong một bảng khác; nó cũng có thể được định nghĩa để tham chiếu các cột của một ràng buộc ĐỘC ĐÁO trong một bảng khác. Câu trả lời có thể được thực hiện để làm việc với các ràng buộc duy nhất bằng cách xóa liên kết cuối cùng và với các chỉ mục duy nhất bằng cách xóa hai liên kết cuối cùng, nhưng điều đó hạn chế thông tin trả về.
Douglas

100

thử: sp_help [table_name]

bạn sẽ nhận được tất cả thông tin về bảng, bao gồm tất cả các khóa ngoại


2
tốt đẹp, rất hữu ích. Đáng nhớ hơn câu trả lời được đánh dấu! không thể tin rằng bạn không thể nhìn thấy chúng trong ssms!
JonnyRaa

4
Rất đẹp, cảm ơn. Nhưng để tìm kiếm FK, tôi thích kết quả từ câu trả lời của Michael bên dưới: sp_fkeys [table]
AjV Jsy

.... hoặc nếu bạn không nhận được kết quả nào từ đó (nhưng sp_help DOES hiển thị khóa ngoại), phiên bản đầy đủ hơn có thể giúp:sp_fkeys @fktable_name='TableName'
AjV Jsy

tuyệt vời! ngắn gọn và súc tích!
zeroflaw

39

Nếu bạn có kế hoạch xóa hoặc đổi tên bảng hoặc cột chỉ tìm phụ thuộc khóa ngoại có thể là không đủ.

Các bảng tham chiếu không được kết nối với khóa ngoại - Bạn cũng cần tìm kiếm các bảng tham chiếu có thể không được kết nối với khóa ngoại (Tôi đã thấy nhiều cơ sở dữ liệu có thiết kế xấu không có khóa ngoại được xác định nhưng có dữ liệu liên quan ). Giải pháp có thể là tìm kiếm tên cột trong tất cả các bảng và tìm kiếm các cột tương tự.

Các đối tượng cơ sở dữ liệu khác - điều này có thể hơi lạc đề nhưng nếu bạn đang tìm kiếm tất cả các tài liệu tham khảo thì việc kiểm tra các đối tượng phụ thuộc cũng rất quan trọng.

Các công cụ GUI - Thử SSMS Tìm các đối tượng có liên quan Tùy chọn hoặc các công cụ như ApexSQL Search (công cụ miễn phí, tích hợp vào SSMS) để xác định tất cả các đối tượng phụ thuộc bao gồm các bảng được kết nối với khóa ngoài.


39

Vì câu hỏi của bạn hướng đến một bảng duy nhất, bạn có thể sử dụng điều này:

EXEC sp_fkeys 'TableName'

Tôi tìm thấy nó trên SO ở đây:

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

Tôi tìm thấy thông tin tôi cần khá nhanh chóng. Nó liệt kê bảng, cột và tên của khóa ngoại.

BIÊN TẬP

Đây là một liên kết đến tài liệu chi tiết các tham số khác nhau có thể được sử dụng: https://docs.microsoft.com/en-us/sql/relational-database/system-stored-procedures/sp-fkeys-transact-sql


29

Tôi nghĩ kịch bản này ít tốn kém hơn:

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

Một cái mà tôi thực sự muốn sử dụng được gọi là Phần mềm theo dõi phụ thuộc SQL của Red Gate Software . Bạn có thể đặt bất kỳ (các) đối tượng cơ sở dữ liệu nào như bảng, thủ tục được lưu trữ, v.v. và sau đó nó sẽ tự động vẽ các đường quan hệ giữa tất cả các đối tượng khác dựa trên (các) mục đã chọn của bạn.

Cung cấp một biểu diễn đồ họa rất tốt của các phụ thuộc trong lược đồ của bạn.


2
Đây cũng là một công cụ tuyệt vời để cho những người phi kỹ thuật biết rằng họ cần phải bỏ ra một số tiền để tái cấu trúc thiết kế cơ sở dữ liệu của họ trước khi tất cả sụp đổ. Các biểu đồ mà nó tạo ra khá hấp dẫn.
Rob Allen

1
Rob: Tôi thích tải toàn bộ lược đồ cơ sở dữ liệu trong đó và sau đó thay đổi giữa các bố cục khác nhau để tôi có thể xem tất cả mọi thứ bay xung quanh.
TheTXI

4

Cảm ơn John Sansom rất nhiều, truy vấn của anh ấy thật tuyệt vời!

Ngoài ra: bạn nên thêm "VÀ PT.ORDINAL_POSITION = CU.ORDINAL_POSITION" vào cuối truy vấn của bạn.

Nếu bạn có nhiều trường trong khóa chính, câu lệnh này sẽ khớp với các trường tương ứng với nhau (tôi đã gặp trường hợp này, truy vấn của bạn đã tạo tất cả các kết hợp, vì vậy đối với 2 trường trong khóa chính, tôi có 4 kết quả cho khóa ngoại tương ứng) .

(Xin lỗi tôi không thể nhận xét câu trả lời của John vì tôi không có đủ điểm danh tiếng).


3

Truy vấn này sẽ trả về chi tiết về các khóa ngoại trong một bảng, nó hỗ trợ nhiều khóa cột.

    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'

2

Sau khi tìm kiếm lâu, tôi tìm thấy một giải pháp làm việc. Cơ sở dữ liệu của tôi không sử dụng sys.forign_key_columns và information_schema.key_column_usage chỉ chứa các khóa chính.

Tôi sử dụng SQL Server 2015

GIẢI PHÁP 1 (hiếm khi được sử dụng)

Nếu các giải pháp khác không hoạt động, điều này sẽ hoạt động tốt:

        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

GIẢI PHÁP 2 (thường được sử dụng)

Trong hầu hết các trường hợp, điều này sẽ hoạt động tốt:

        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

Bạn có thể sử dụng Information_SCHema.KEY_COLUMN_USAGE và sys.forign_key_columns để lấy siêu dữ liệu khóa ngoài cho một bảng, ví dụ như tên ràng buộc, bảng tham chiếu và cột tham chiếu, v.v.

Dưới đây là truy vấn:

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

Chỉ cần một lưu ý cho câu trả lời @ "John Sansom",

Nếu các phụ thuộc khóa ngoại được tìm kiếm, tôi nghĩ rằng mệnh đề PT Where phải là:

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

và điều kiện BẬT :

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

Như thường được sử dụng khóa chính của bảng nước ngoài, tôi nghĩ vấn đề này chưa được chú ý trước đây.


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

Nó sẽ cung cấp cho bạn:

Bản thân FK Schema mà FK thuộc về

  • "Bảng tham chiếu" hoặc bảng có FK
  • "Cột tham chiếu" hoặc cột bên trong bảng tham chiếu trỏ đến FK
  • "Bảng tham chiếu" hoặc bảng có cột khóa mà FK của bạn đang trỏ đến
  • "Cột được tham chiếu" hoặc cột là khóa mà FK của bạn đang trỏ đến

-1

SỬ DỤNG thông tin_schema;

SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.