2010-10-11 12 views
28

Trong SQL Server, làm thế nào tôi có thể lấy tên bảng + tham chiếu từ khóa ngoài?Máy chủ SQL: Làm cách nào để lấy tham chiếu khóa ngoài từ information_schema?

Lưu ý: Không phải bảng/cột có khóa, nhưng khóa đó đề cập đến.

Ví dụ:

Khi phím [FA_MDT_ID] trong bảng [T_ALV_Ref_FilterDisplay]. đề cập đến [T_AP_Ref_Customer].[MDT_ID]

như khi tạo một hạn chế như thế này:

ALTER TABLE [dbo].[T_ALV_Ref_FilterDisplay] WITH CHECK ADD CONSTRAINT [FK_T_ALV_Ref_FilterDisplay_T_AP_Ref_Customer] FOREIGN KEY([FA_MDT_ID]) 
REFERENCES [dbo].[T_AP_Ref_Customer] ([MDT_ID]) 
GO 

tôi cần để có được [T_AP_Ref_Customer].[MDT_ID] khi trao [T_ALV_Ref_FilterAnzeige].[FA_MDT_ID] như là đầu vào

Trả lời

63

Đừng bận tâm, đây là câu trả lời đúng:
http://msdn.microsoft.com/en-us/library/aa175805(SQL.80).aspx

SELECT 
    KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME 
    ,KCU1.TABLE_NAME AS FK_TABLE_NAME 
    ,KCU1.COLUMN_NAME AS FK_COLUMN_NAME 
    ,KCU1.ORDINAL_POSITION AS FK_ORDINAL_POSITION 
    ,KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME 
    ,KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME 
    ,KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME 
    ,KCU2.ORDINAL_POSITION AS REFERENCED_ORDINAL_POSITION 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC 

INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU1 
    ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
    AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
    AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 

INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU2 
    ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG 
    AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA 
    AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME 
    AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION 
+3

Cảnh báo! - Điều này không trả lại các fks tham chiếu các cột chỉ mục duy nhất. Xem http://stackoverflow.com/questions/2895219/can-we-have-a-foreign-key-which-is-not-a-primary-key-in-any-other-table. –

+2

@ Reno Reno: Đây là chính xác trong Microsoft SQL Server, bởi vì ở đó bạn có thể tham khảo một chỉ mục duy nhất trong một khóa ngoại. Nhưng tiêu chuẩn SQL không cho phép điều này và điều này không được hỗ trợ bởi tất cả các DBMS khác. Ngoài ra, không có thông tin chỉ mục có sẵn trong information_schema, vì vậy không có cách nào để sửa lỗi này. Tôi muốn nói nếu bạn không tham khảo một khóa chính là khóa ngoài, bạn đang làm một cái gì đó sai lược đồ khôn ngoan. –

+0

Truy vấn này hầu như hoạt động chính xác cho tôi. Tôi đã thêm 'AND KCU2.TABLE_NAME = RC.REFERENCED_TABLE_NAME' vào mệnh đề ON của KCU2 JOIN để loại bỏ các bản ghi không chính xác do nhiều bảng trong cơ sở dữ liệu của tôi với khóa chính có tên là' PRIMARY'. Tôi xảy ra để chạy MariaDB 5.5, nhưng tôi nghi ngờ DBMS khác sẽ có một vấn đề tương tự. – JSmitty

13

Nếu bạn có thể sống với việc sử dụng SQL Server schema cụ thể chế độ xem danh mục, truy vấn này sẽ trả lại nội dung bạn đang tìm kiếm:

SELECT 
    fk.name, 
    OBJECT_NAME(fk.parent_object_id) 'Parent table', 
    c1.name 'Parent column', 
    OBJECT_NAME(fk.referenced_object_id) 'Referenced table', 
    c2.name 'Referenced column' 
FROM 
    sys.foreign_keys fk 
INNER JOIN 
    sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id 
INNER JOIN 
    sys.columns c1 ON fkc.parent_column_id = c1.column_id AND fkc.parent_object_id = c1.object_id 
INNER JOIN 
    sys.columns c2 ON fkc.referenced_column_id = c2.column_id AND fkc.referenced_object_id = c2.object_id 

Không chắc thế nào - nếu có - bạn có thể nhận được các thông tin tương tự từ các quan điểm INFORMATION_SCHEMA ....

+0

37'874 phím nước ngoài trong cơ sở dữ liệu của tôi với khoảng 100 bảng? Tôi không chắc, nhưng tôi không nghĩ nó đúng. Tôi nhận được 349, mà tôi nghĩ là có nhiều khả năng ... –

+2

@Quandary: xin lỗi, bỏ lỡ một vài điều kiện ON - điều này sẽ tốt hơn bây giờ (làm việc cho tôi, anyway) –

+0

Cách tham gia nội bộ này với INFORMATION_SCHEMA.KEY_COLUMN_USAGE để nhận ORDINAL_POSITION của trường? –

0

tôi muốn aa phiên bản sẽ cho phép tôi tìm tất cả các cột "Key" và "ID" có/thiếu một ràng buộc. Vì vậy, tôi muốn tất cả các cột so với danh sách tất cả PK HOẶC FK HOẶC Không, đây là truy vấn của tôi. Hy vọng nó sẽ giúp người khác!

SELECT 
    c.table_schema 
    ,c.table_name 
    ,c.column_name 
    ,KeyConstraints.constraint_type 
    ,KeyConstraints.constraint_schema 
    ,KeyConstraints.constraint_name 
    ,KeyConstraints.referenced_table_schema 
    ,KeyConstraints.referenced_table_name 
    ,KeyConstraints.referenced_column_name 
    ,KeyConstraints.update_rule 
    ,KeyConstraints.delete_rule 
FROM information_schema.columns AS c 
LEFT JOIN 
    (
     SELECT 
      FK.table_schema AS TABLE_SCHEMA 
      ,FK.table_name 
      ,CU.column_name 
      ,FK.constraint_type 
      ,c.constraint_schema 
      ,C.constraint_name 
      ,PK.table_schema AS REFERENCED_TABLE_SCHEMA 
      ,PK.table_name AS REFERENCED_TABLE_NAME 
      ,CCU.column_name AS REFERENCED_COLUMN_NAME 
      ,C.update_rule 
      ,C.delete_rule 
     FROM information_schema.referential_constraints AS C 

     INNER JOIN information_schema.table_constraints AS FK 
      ON C.constraint_name = FK.constraint_name 

     INNER JOIN information_schema.table_constraints AS PK 
      ON C.unique_constraint_name = PK.constraint_name 

     INNER JOIN information_schema.key_column_usage AS CU 
      ON C.constraint_name = CU.constraint_name 

     INNER JOIN information_schema.constraint_column_usage AS CCU 
      ON PK.constraint_name = CCU.constraint_name 

     WHERE (FK.constraint_type = 'FOREIGN KEY') 

     UNION 

     SELECT 
      ccu.table_schema 
      ,ccu.table_name 
      ,ccu.column_name 
      ,tc.constraint_type 
      ,ccu.constraint_schema 
      ,ccu.constraint_name 
      ,NULL 
      ,NULL 
      ,NULL 
      ,NULL 
      ,NULL 
     FROM information_schema.constraint_column_usage ccu 

     INNER JOIN information_schema.table_constraints tc 
      ON ccu.table_schema = tc.table_schema 
      AND ccu.table_name = tc.table_name 

     WHERE tc.constraint_type = 'PRIMARY KEY' 

    ) AS KeyConstraints 
    ON c.table_schema = KeyConstraints.table_schema 
    AND c.table_name = KeyConstraints.table_name 
    AND c.column_name = KeyConstraints.column_name 

WHERE c.column_name LIKE '%ID' OR c.column_name LIKE '%Key' 
ORDER BY c.table_schema 
     ,c.table_name 
     ,c.column_name 
; 

định dạng lịch sự của: http://www.dpriver.com/pp/sqlformat.htm

+0

Hãy dành thời gian để chuyển sang các tùy chọn thích hợp khi sử dụng sqlformat. Phiên bản của bạn hoàn toàn không thể đọc được. Sửa lỗi đó. Ngoài ra, hãy sử dụng AS khi khai báo một bí danh. Điều đó sẽ giúp bạn tránh được rất nhiều vấn đề tiềm năng.SqlFormat sẽ định dạng cho bạn, nhưng nó không nghĩ cho bạn. –

+0

@StefanSteiger cảm ơn phản hồi. Tôi đã không đăng lên các truy vấn dài trên SO thường vì vậy không chắc chắn về các tùy chọn tốt nhất để sử dụng. tôi sẽ ghi nhớ điều này trong lần sau. Tôi cũng sẽ cố gắng và nhớ để bao gồm các "AS" vòng loại, đây là một thói quen xấu tôi đang liên tục làm việc để cải thiện trên! – Justin