주어진 기본 키와 관련된 외래 키 찾기


19

주어진 데이터베이스에서 어떤 열이 PK / FK 관계를 통해 결합되는지를 설정하는 방법을 원합니다. 주어진 테이블에 대한 PK / FK 정보를 통해

SELECT *  
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS cu 
WHERE EXISTS (
    SELECT tc.* 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc 
    WHERE tc.CONSTRAINT_CATALOG = 'MyDatabase'  
        AND tc.TABLE_NAME = 'MyTable'  
        /*AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'*/
        AND tc.CONSTRAINT_NAME = cu.CONSTRAINT_NAME);
GO

그러나 그러한 쿼리에서 반환 된 PK의 경우 관련 FK를 설정하는 방법은 무엇입니까?

나는 또한 당신이 참조 테이블을 얻을 수 있다는 것을 알고있다 :

SELECT CONSTRAINT_NAME = name, 
       FOREIGN_SCHEMA = OBJECT_SCHEMA_NAME(parent_object_id), 
       FOREIGN_TABLE = OBJECT_NAME(parent_object_id), 
       REFERENCED_SCHEMA = OBJECT_SCHEMA_NAME(referenced_object_id), 
       REFERENCED_TABLE = OBJECT_NAME(referenced_object_id) 
FROM sys.foreign_keys
WHERE OBJECT_NAME(referenced_object_id) = 'MyTable';
GO

하지만 지금은 명시 적 열 참조를 얻기 위해 고심하고 있습니다.

QlikView 용 스크립트 생성기를 만들고 있습니다. 스크립트를 생성하려면 제약 조건과 관련 링크가 필요합니다. 주어진 열 (있는 경우)에 대한 모든 제약 조건 정보가 필요합니다.

주어진 데이터베이스에 대한 모든 정보를 보유하는 데이터베이스 클래스를 만들고 싶습니다. 이 클래스 구조 database.table.column.constraints는 PK / FK의 서로 다른 열 사이의 일치를 가져 오는 데 사용됩니다.

분명히 일부 열에는 FK 만 있고이 경우 해당 키의 PK 정보도 검색하려고합니다. 일부는 PK 만 가질 것이고 그 반대의 것을 원합니다. 물론 일부는 둘 다 가질 수 있습니다.

답변:


35

외래 키를 참조 테이블 / 열에 일치시키는 간단한 쿼리는 다음과 같습니다.

SELECT
    o1.name AS FK_table,
    c1.name AS FK_column,
    fk.name AS FK_name,
    o2.name AS PK_table,
    c2.name AS PK_column,
    pk.name AS PK_name,
    fk.delete_referential_action_desc AS Delete_Action,
    fk.update_referential_action_desc AS Update_Action
FROM sys.objects o1
    INNER JOIN sys.foreign_keys fk
        ON o1.object_id = fk.parent_object_id
    INNER JOIN sys.foreign_key_columns fkc
        ON fk.object_id = fkc.constraint_object_id
    INNER JOIN sys.columns c1
        ON fkc.parent_object_id = c1.object_id
        AND fkc.parent_column_id = c1.column_id
    INNER JOIN sys.columns c2
        ON fkc.referenced_object_id = c2.object_id
        AND fkc.referenced_column_id = c2.column_id
    INNER JOIN sys.objects o2
        ON fk.referenced_object_id = o2.object_id
    INNER JOIN sys.key_constraints pk
        ON fk.referenced_object_id = pk.parent_object_id
        AND fk.key_index_id = pk.unique_index_id
ORDER BY o1.name, o2.name, fkc.constraint_column_id

출력에는 외래 키의 테이블 및 열 이름 (FK_table, FK_column), 외래 키 제약 조건의 이름 (FK_name), 참조 된 PK 또는 고유 인덱스 테이블 및 열 이름 (PK_table, PK_column), 참조 된 PK 또는 고유 색인의 이름 (PK_name) 및 갱신 / 삭제 계단식 조치 (Delete_Action, Update_Action).

(출력 열을 더 추가하도록 편집되었습니다.)

편집 : 6 년 후에 개선 된 버전으로 돌아 왔습니다. 원래 쿼리가 실제로 다중 열 외래 키를 제대로 처리하지 못한다는 것을 깨달았으며 비활성화되거나 신뢰할 수 없거나 색인이 생성되지 않은 외래 키를 신속하게 식별하고 싶었습니다. 이 모든 것을 수정하는 새로운 버전이 있습니다.

여러 열 키는 전통적인 / 남용을 사용하여 FK_columns및 로 쉼표로 구분 된 목록으로 표시됩니다 . 이 열에는 외래 키 열 (주로 기본 키 테이블에 대한 삭제 또는 업데이트를 최적화하는 데 사용)을 사용하여 검색을 만족시키는 데 사용될 수있는 외래 키 테이블의 인덱스 이름이 표시됩니다. 이 경우 인덱싱되지 않은 외래 키가 있습니다. PK 테이블 이름을 기준으로 정렬하거나 특정 PK / FK 테이블을 필터링하는 등의 방법 으로을 조정 하거나 절 (아래 주석)을 추가 할 수 있습니다 .PK_columnsFOR XMLSTUFFFK_indexesNULLORDER BYWHERE

SELECT
    fk.is_disabled,
    fk.is_not_trusted,
    OBJECT_SCHEMA_NAME(o1.object_id) AS FK_schema,
    o1.name AS FK_table,
    --Generate list of columns in referring side of foreign key
    STUFF(
        (
            SELECT ', ' + c1.name AS [text()]
            FROM sys.columns c1 INNER
                JOIN sys.foreign_key_columns fkc
                    ON c1.object_id = fkc.parent_object_id
                    AND c1.column_id = fkc.parent_column_id
            WHERE fkc.constraint_object_id = fk.object_id
            FOR XML PATH('')
        ), 1, 2, '') AS FK_columns,
    --Look for any indexes that will fully satisfy the foreign key columns
    STUFF(
        (
            SELECT ', ' + i.name AS [text()]
            FROM sys.indexes i
            WHERE i.object_id = o1.object_id
                AND NOT EXISTS ( --Find foreign key columns that don't match the index key columns
                    SELECT fkc.constraint_column_id, fkc.parent_column_id
                    FROM sys.foreign_key_columns fkc
                    WHERE fkc.constraint_object_id = fk.object_id
                    EXCEPT
                    SELECT ic.key_ordinal, ic.column_id
                    FROM sys.index_columns ic
                    WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id
                )
            FOR XML PATH('')
        ), 1, 2, '') AS FK_indexes,
    fk.name AS FK_name,
    OBJECT_SCHEMA_NAME(o2.object_id) AS PK_schema,
    o2.name AS PK_table,
    --Generate list of columns in referenced (i.e. PK) side of foreign key
    STUFF(
        (
            SELECT ', ' + c2.name AS [text()]
            FROM sys.columns c2
                INNER JOIN sys.foreign_key_columns fkc
                    ON c2.object_id = fkc.referenced_object_id
                    AND c2.column_id = fkc.referenced_column_id
            WHERE fkc.constraint_object_id = fk.object_id
            FOR XML PATH('')
        ), 1, 2, '') AS PK_columns,
    pk.name AS PK_name,
    fk.delete_referential_action_desc AS Delete_Action,
    fk.update_referential_action_desc AS Update_Action
FROM sys.objects o1
    INNER JOIN sys.foreign_keys fk
        ON o1.object_id = fk.parent_object_id
    INNER JOIN sys.objects o2
        ON fk.referenced_object_id = o2.object_id
    INNER JOIN sys.key_constraints pk
        ON fk.referenced_object_id = pk.parent_object_id
        AND fk.key_index_id = pk.unique_index_id
--WHERE o2.name = 'Company_Address'
ORDER BY o1.name, o2.name

7

이 쿼리는 데이터베이스의 모든 FK 관계 (FK 제약 조건 이름, 참조 테이블의 스키마 / 테이블, 참조 열 이름, 참조 테이블의 스키마 / 테이블 및 참조 열 이름)를 모두 제공합니다. 다중 열 제약 조건에 대해 여러 행이 있습니다.

SELECT 
    FK = OBJECT_NAME(pt.constraint_object_id),
    Referencing_table = QUOTENAME(OBJECT_SCHEMA_NAME(pt.parent_object_id))
            + '.' + QUOTENAME(OBJECT_NAME(pt.parent_object_id)),
    Referencing_col = QUOTENAME(pc.name), 
    Referenced_table = QUOTENAME(OBJECT_SCHEMA_NAME(pt.referenced_object_id)) 
            + '.' + QUOTENAME(OBJECT_NAME(pt.referenced_object_id)),
    Referenced_col = QUOTENAME(rc.name)
FROM sys.foreign_key_columns AS pt
INNER JOIN sys.columns AS pc
ON pt.parent_object_id = pc.[object_id]
AND pt.parent_column_id = pc.column_id
INNER JOIN sys.columns AS rc
ON pt.referenced_column_id = rc.column_id
AND pt.referenced_object_id = rc.[object_id]
ORDER BY Referencing_table, FK, pt.constraint_column_id;

특정 기본 키 제약 조건 의 열 뒤에 있고 해당 PK 제약 조건의 이름을 이미 알고 있다면 다음 과 같이 작성할 수 있습니다.

DECLARE @PK_Constraint SYSNAME = N'Name of PK constraint';

SELECT
    FK = OBJECT_NAME(fkc.constraint_object_id),
    Referencing_table = QUOTENAME(OBJECT_SCHEMA_NAME(fkc.parent_object_id))
            + '.' + QUOTENAME(OBJECT_NAME(fkc.parent_object_id)),
    Referencing_col = QUOTENAME(pc.name), 
    Referenced_table = QUOTENAME(OBJECT_SCHEMA_NAME(fkc.referenced_object_id)) 
            + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)),
    Referenced_col = QUOTENAME(rc.name)
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.columns AS pc
ON fkc.parent_object_id = pc.[object_id]
AND fkc.parent_column_id = pc.column_id
INNER JOIN sys.columns AS rc
ON fkc.referenced_column_id = rc.column_id
AND fkc.referenced_object_id = rc.[object_id]
WHERE EXISTS 
(
  SELECT 1 FROM sys.indexes AS i
  INNER JOIN sys.foreign_keys AS fk
  ON i.[object_id] = fk.referenced_object_id
  AND i.index_id = fk.key_index_id
  AND fk.[object_id] = fkc.constraint_object_id
  AND i.name = @PK_Constraint
)
ORDER BY Referencing_table, FK, fkc.constraint_column_id;

PK 이름을 다른 정보와 함께 포함하려면 다음을 수행하십시오.

SELECT 
    FK = OBJECT_NAME(fkc.constraint_object_id),
    Referencing_table = QUOTENAME(OBJECT_SCHEMA_NAME(fkc.parent_object_id))
            + '.' + QUOTENAME(OBJECT_NAME(fkc.parent_object_id)),
    Referencing_col = QUOTENAME(pc.name),
    Referenced_table = QUOTENAME(OBJECT_SCHEMA_NAME(fkc.referenced_object_id)) 
            + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)),
    Referenced_col = QUOTENAME(rc.name),
    PK = pk.name
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.columns AS pc
ON fkc.parent_object_id = pc.[object_id]
AND fkc.parent_column_id = pc.column_id
INNER JOIN sys.columns AS rc
ON fkc.referenced_column_id = rc.column_id
AND fkc.referenced_object_id = rc.[object_id]
INNER JOIN (SELECT i.name, fk.[object_id]
  FROM sys.indexes AS i
  INNER JOIN sys.foreign_keys AS fk
  ON i.[object_id] = fk.referenced_object_id
  AND i.index_id = fk.key_index_id
) AS pk
ON pk.[object_id] = fkc.constraint_object_id
ORDER BY Referencing_table, FK, fkc.constraint_column_id;

행 목록에 쉼표로 구분 된 목록 또는 개별 열로 열 목록을 가져 오는 트릭도 있지만, 정확히 어떤 형식을 알 때까지 이러한 쿼리를 수정하기 위해 이러한 쿼리를 수정하는 데 투자하지는 않습니다. 당신은 후입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.