복붙노트

[SQL] 비 기본 키 외래 키

SQL

비 기본 키 외래 키

나는 데이터를 보유하고, 해당 행 중 하나가 다른 테이블에 존재해야하는 테이블이 있습니다. 그래서, 외래 키가 참조 무결성을 유지합니다.

CREATE TABLE table1
(
   ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
   AnotherID INT NOT NULL,
   SomeData VARCHAR(100) NOT NULL
)

CREATE TABLE table2
(
   ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
   AnotherID INT NOT NULL,
   MoreData VARCHAR(30) NOT NULL,

   CONSTRAINT fk_table2_table1 FOREIGN KEY (AnotherID) REFERENCES table1 (AnotherID)
)

당신이 볼 수 그러나, 열을 테이블 I 외래 키는 PK 없습니다. 이 외래 키, 아니면이 참조 무결성을 유지하기 위해 더 나은 방법을 만들 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.정말 기본이 아닌 키에 대한 외부 키를 만들려면, 그것의 고유 제한 조건이있는 열 수 있어야한다.

    정말 기본이 아닌 키에 대한 외부 키를 만들려면, 그것의 고유 제한 조건이있는 열 수 있어야한다.

    온라인에서 :

    따라서 귀하의 경우는 AnotherID 독특한 할 경우에는 허용됩니다. 고유 한 제약 조건을 적용 할 수없는 경우에 당신은 운이,하지만 당신이 그것에 대해 생각한다면이 정말 메이크업 감각을한다.

    같은 언급되었지만 당신이 후보 키와 완벽하게 좋은 기본 키가있는 경우, 그 이유를 사용하지?

  2. ==============================

    2.다른 사람들이 지적했듯이, 이상적으로, 외래 키는 기본 키 (일반적으로 IDENTITY 열)에 대한 참조로 생성 될 것이다. 그러나, 우리는 이상적인 세계에 거주하지 않는, 때로는 스키마에 "작은"변화는 응용 프로그램 논리에 상당한 파급 효과를 가질 수 있습니다.

    다른 사람들이 지적했듯이, 이상적으로, 외래 키는 기본 키 (일반적으로 IDENTITY 열)에 대한 참조로 생성 될 것이다. 그러나, 우리는 이상적인 세계에 거주하지 않는, 때로는 스키마에 "작은"변화는 응용 프로그램 논리에 상당한 파급 효과를 가질 수 있습니다.

    SSN을 열 (그리고 바보 기본 키), 또한 SSN 열이 포함 된 청구 테이블 고객 테이블의 경우 고려 (고객 데이터에서 비즈니스 로직에 의해 채워을,하지만 FK는 존재하지 않는다). 디자인은 결함이 있지만, 몇 년 동안 사용되어 왔으며, 세 가지 다른 응용 프로그램은 스키마에 건설되었다. Claim.SSN에서 추출하고 실제 PK-FK 관계에 두는 것이 이상적 일 것입니다 분명해야하지만, 또한 중요한 점검 할 것이다. 반면에, 거의 또는 응용 프로그램에 영향을주지 않고, 참조 무결성을 제공 할 수있다, Customer.SSN에 UNIQUE 제약을 가하고, 그리고 Claim.SSN에 FK를 추가.

    오해하지 마세요, 가끔 이상주의를 통해 실용주의의 승리를 정상화에 대한 모든이야,하지만. 평범한 디자인이 반창고와 도움이 될 수있는 경우, 수술을 피할 수 있습니다.

  3. ==============================

    3.Necromancing. 나는 누군가가 여기에 착륙 할 때, 그는 비 고유 키가 들어있는 테이블의 컬럼에 외래 키를 필요로 가정합니다. 문제는 당신이 그 문제가있을 경우, 데이터베이스 스키마가 비정규되어있다.

    Necromancing. 나는 누군가가 여기에 착륙 할 때, 그는 비 고유 키가 들어있는 테이블의 컬럼에 외래 키를 필요로 가정합니다. 문제는 당신이 그 문제가있을 경우, 데이터베이스 스키마가 비정규되어있다.

    당신은 방 UID 기본 키, 테이블의 예를 유지 객실에 대한있어하는 DateFrom과 DateTo 필드, 다른 UID가 여기에 같은 방을 추적하는 RM_ApertureID 및 소프트 삭제 필드, RM_Status 같은, 여기서 99 수단은 '삭제'와 <> 99 개 수단 '활성'.

    그래서 당신은 RM_UID와 같은 값으로 RM_UID 및 RM_ApertureID 삽입을 처음 방을 만들 때. 당신이 날짜로 방을 종료하고 새 날짜 범위를 재 확립 할 때 다음, RM_UID)은 (NEWID이며, 이전 항목에서 RM_ApertureID는 새로운 RM_ApertureID된다.

    그런 경우 경우에 따라서, RM_ApertureID는 고유하지 않은 분야이고, 그래서 당신은 다른 테이블의 외래 키를 설정할 수 없습니다.

    그리고 고유하지 않은 컬럼 / 인덱스, 예를 들어,에 외래 키를 설정하는 방법은 없습니다 T_ZO_REM_AP_Raum_Reinigung에서 (RM_UID 실제로 RM_ApertureID입니다). 그러나 잘못된 값을 금지, 그렇지 않으면, 데이터 쓰레기가 조속히 결과, 외래 키를 설정해야합니다 ...

    이제 당신이 (이 경우 전체 응용 프로그램을 다시 작성의 짧은을) 할 수있는 것은 키의 존재를 확인 스칼라 기능을하는 CHECK-제약 조건을 삽입 할 수 있습니다 :

    IF  EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]'))
    ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung DROP CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
    GO
    
    
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_Constaint_ValidRmApertureId]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
    DROP FUNCTION [dbo].[fu_Constaint_ValidRmApertureId]
    GO
    
    
    
    
    CREATE FUNCTION [dbo].[fu_Constaint_ValidRmApertureId](
         @in_RM_ApertureID uniqueidentifier 
        ,@in_DatumVon AS datetime 
        ,@in_DatumBis AS datetime 
        ,@in_Status AS integer 
    ) 
        RETURNS bit 
    AS 
    BEGIN   
        DECLARE @bNoCheckForThisCustomer AS bit 
        DECLARE @bIsInvalidValue AS bit 
        SET @bNoCheckForThisCustomer = 'false' 
        SET @bIsInvalidValue = 'false' 
    
        IF @in_Status = 99 
            RETURN 'false' 
    
    
        IF @in_DatumVon > @in_DatumBis 
        BEGIN 
            RETURN 'true' 
        END 
    
    
        IF @bNoCheckForThisCustomer = 'true'
            RETURN @bIsInvalidValue 
    
    
        IF NOT EXISTS
        ( 
            SELECT 
                 T_Raum.RM_UID 
                ,T_Raum.RM_Status 
                ,T_Raum.RM_DatumVon 
                ,T_Raum.RM_DatumBis 
                ,T_Raum.RM_ApertureID 
            FROM T_Raum 
            WHERE (1=1) 
            AND T_Raum.RM_ApertureID = @in_RM_ApertureID 
            AND @in_DatumVon >= T_Raum.RM_DatumVon 
            AND @in_DatumBis <= T_Raum.RM_DatumBis 
            AND T_Raum.RM_Status <> 99  
        ) 
            SET @bIsInvalidValue = 'true' -- IF ! 
    
        RETURN @bIsInvalidValue 
    END 
    
    
    
    GO
    
    
    
    IF  EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]'))
    ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung DROP CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
    GO
    
    
    -- ALTER TABLE dbo.T_AP_Kontakte WITH CHECK ADD CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]  
    ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung WITH NOCHECK ADD CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung] 
    CHECK 
    ( 
        NOT 
        ( 
            dbo.fu_Constaint_ValidRmApertureId(ZO_RMREM_RM_UID, ZO_RMREM_GueltigVon, ZO_RMREM_GueltigBis, ZO_RMREM_Status) = 1 
        ) 
    ) 
    GO
    
    
    IF  EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]')) 
    ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung CHECK CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung] 
    GO
    
  4. ==============================

    4.항상 고유해야 할 필요가 기본 키, 외래 키 테이블은 일대 다 관계의 경우 고유하지 않은 값을 허용해야합니다. 또한 테이블이 일대일 관계가 아니라 일대 다 관계에 의해 연결되어있는 경우 기본 키로 외부 키를 사용하여 완벽하게 괜찮습니다.

    항상 고유해야 할 필요가 기본 키, 외래 키 테이블은 일대 다 관계의 경우 고유하지 않은 값을 허용해야합니다. 또한 테이블이 일대일 관계가 아니라 일대 다 관계에 의해 연결되어있는 경우 기본 키로 외부 키를 사용하여 완벽하게 괜찮습니다.

    외래 키 제약 조건은 다른 테이블의 PRIMARY KEY 제약 조건에만 연결 할 필요가 없습니다; 또한, 다른 테이블에 UNIQUE 제약의 열을 참조하도록 정의 될 수있다.

  5. from https://stackoverflow.com/questions/18435065/foreign-key-to-non-primary-key by cc-by-sa and MIT license