여러 테이블에서 기본 키를 참조하는 외래 키?


91

직원 데이터베이스 아래에 두 개의 테이블, 즉 employee_ce 및 employee_sn이 있습니다.

둘 다 고유 한 기본 키 열이 있습니다.

deductions라는 또 다른 테이블이 있는데, 그 외래 키 열은 employee_ce 및 employee_sn의 기본 키를 참조합니다. 이게 가능해?

예를 들면

employees_ce
--------------
empid   name
khce1   prince

employees_sn
----------------
empid   name
khsn1   princess

이것이 가능합니까?

deductions
--------------
id      name
khce1   gold
khsn1   silver

답변:


98

내가 귀하의 시나리오를 올바르게 이해했다고 가정하면 이것이 올바른 방법 이라고 부를 것입니다 .

데이터베이스에 대한 높은 수준의 설명에서 시작하십시오! 직원이 있고 직원은 "ce"직원과 "sn"직원이 될 수 있습니다. 객체 지향 용어로 "employee"클래스가 있으며 "ce employee"와 "sn employee"라는 두 개의 하위 클래스가 있습니다.

그런 다음이 상위 수준 설명을 employees, employees_ceemployees_sn:의 세 테이블로 변환합니다 .

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

모든 직원이 직원이기 때문에 (duh!) 모든 직원은 employees테이블에 행이 있습니다 . "ce"직원도 employees_ce테이블에 행이 있고 "sn"직원도 employees_sn테이블에 행이 있습니다. employees_ce.id에 외래 키 employees.id것처럼 employees_sn.id입니다.

모든 종류의 직원 (ce 또는 sn)을 참조하려면 employees표를 참조하십시오 . 즉, 문제가 발생한 외래 키는 해당 테이블을 참조해야합니다!


17
ce와 sn을 상호 배타적으로 만드는 방법은 무엇입니까? 직원은 동시에 ce와 sn이 될 수 없으므로 데이터베이스에 반영하는 것이 좋습니다. 지금이 문제가 있습니다.
Rolf 2011

여러 열 키가 이전 의견의 문제에 도움이 될 수 있다고 생각합니다.
Rolf

12
기본 테이블과 파생 테이블에 유형을 저장하여 직원이 하나의 테이블 (및 올바른 테이블)에만 있도록 강제 할 수 있습니다. 기본 키 ID, (id, type)의 고유 키, 자식 테이블의 외래 키 (id, type)를 설정하고 올바른 유형 만 갖도록 각 자식 테이블에 CHECK 제약 조건을 적용합니다. 또는 데이터베이스가 전역 검사 제약을 수행하는 경우 (그리고 엄청난 속도 저하없이) 물론 NOT EXISTS 검사를 수행 할 수 있습니다.
derobert

전체 설명 및 구현 세부 사항은 이 답변 을 확인 하십시오.
PerformanceDBA

특정 ID를 가진 직원이 'se'또는 'sn'인지 어떻게 알 수 있습니까?
mhrsalehi

22

두 개의 외래 키 제약 조건을 추가 할 수 있지만 (솔직히 시도해 본 적이 없습니다) 두 테이블에 부모 행이 존재한다고 주장합니다.

대신 두 종업원 하위 유형에 대한 상위 유형을 만든 다음 대신 외래 키를 가리킬 수 있습니다. (물론 두 가지 유형의 직원을 분할해야하는 타당한 이유가 있다고 가정합니다.)

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name

type직원 테이블에서 ce또는 sn.


여러 외래 키를 추가하려고 시도했지만 작동했지만 레코드를 추가하는 동안 java derby가 두 외래 키 제약 조건을 모두 위반했다고 알려줍니다!

방금 PostgreSQL에서 시도했는데 거기에서 작동합니다. 두 테이블 모두에 상위 레코드가 있습니까?
derobert

당신이 말하는 부모 기록, empid?

확실히 문제는 "공제"테이블에서 "직원"테이블로 옮겨졌습니다. 유형에 따라 잠재적으로 다른 엔티티를 어떻게 참조합니까?
gawpertron

1
@gawpertron : 음, empid는 모든 유형에서 고유합니다. 'type'필드를 사용하여 참조해야하는 하위 테이블을 확인할 수 있습니다. 또는 LEFT JOIN충분히 적은 경우 모두. 'employee'기본 테이블을 사용하지 않는 경우 기본 키를 선언 할 수 없습니다 (tableA 또는 tableB를 참조하거나 ...). 이제 그럴 수 있습니다. 분할의 지혜 employees_ceemployees_sn상정, 그 상정이 주목됩니다.
derobert

19

사실 제가 직접합니다. 3 개의 다른 테이블에있는 레코드에 대한 주석이 포함 된 'Comments'라는 테이블이 있습니다. 두 솔루션 모두 실제로 원하는 모든 것을 처리하지 않습니다. 귀하의 경우 다음을 수행합니다.

해결책 1 :

  1. 각각의 테이블에서 다른 기본값을 가진 tinyint 필드를 employee_ce 및 employee_sn에 추가합니다 (이 필드는 '테이블 식별자'를 나타내므로이를 tid_ce 및 tid_sn이라고합니다).

  2. 테이블의 PK 및 테이블 ID 필드를 사용하여 각 테이블에 고유 인덱스를 만듭니다.

  3. 'Deductions'테이블에 tinyint 필드를 추가하여 외래 키 (테이블 ID)의 후반부를 저장합니다.

  4. '공제'테이블에 외래 키 2 개를 만듭니다 (한 키가 유효하거나 다른 키가 유효하기 때문에 참조 무결성을 적용 할 수 없습니다.

    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_ce] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce]
    GO
    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_sn] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn]
    GO
    
    employees_ce
    --------------
    empid    name     tid
    khce1   prince    1
    
    employees_sn
    ----------------
    empid    name     tid 
    khsn1   princess  2
    
    deductions
    ----------------------
    id      tid       name  
    khce1   1         gold
    khsn1   2         silver         
    ** id + tid creates a unique index **

솔루션 2 : 이 솔루션을 사용하면 참조 무결성을 유지할 수 있습니다. 1. 'Deductions'테이블에 두 번째 외래 키 필드를 만들고 두 외래 키 모두에 Null 값을 허용하고 일반 외래 키를 만듭니다.

    employees_ce
    --------------
    empid   name
    khce1   prince 

    employees_sn
    ----------------
    empid   name     
    khsn1   princess 

    deductions
    ----------------------
    idce    idsn      name  
    khce1   *NULL*    gold
    *NULL*  khsn1     silver         

무결성은 열이 널이 아닌 경우에만 확인되므로 참조 무결성을 유지할 수 있습니다.


6

나는 이것이 오랫동안 정체 된 주제라는 것을 알고 있지만 여기에서 검색하는 사람은 다중 테이블 외래 키를 다루는 방법입니다. 이 기술을 사용하면 DBA 강제 캐스케이드 작업이 없으므로 DELETE코드에서 이러한 작업을 처리해야합니다.

Table 1 Fruit
pk_fruitid, name
1, apple
2, pear

Table 2 Meat
Pk_meatid, name
1, beef
2, chicken

Table 3 Entity's
PK_entityid, anme
1, fruit
2, meat
3, desert

Table 4 Basket (Table using fk_s)
PK_basketid, fk_entityid, pseudo_entityrow
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table)
2, 1, 1 (Apple)
3, 1, 2 (pear)
4, 3, 1 (cheesecake)

SO Op의 예제는 다음과 같습니다.

deductions
--------------
type    id      name
1      khce1   gold
2      khsn1   silver

types
---------------------
1 employees_ce
2 employees_sn

1

기술적으로 가능합니다. 공제에서 employee_ce를 참조하고 employee_sn을 참조하십시오. 하지만 employee_sn과 employee_ce를 병합하지 않는 이유는 무엇입니까? 나는 당신이 두 개의 테이블을 가진 이유를 알지 못합니다. 일대 다 관계가 없습니다. 그리고 (이 예에서는 아님) 많은 열.

한 열에 대해 두 개의 참조를 수행하는 경우 직원 두 테이블 모두에 항목이 있어야합니다 .


1

예, 가능합니다. 세 번째 테이블에 대해 2 개의 FK를 정의해야합니다. 한 테이블의 필수 필드를 가리키는 각 FK (즉, 외부 테이블 당 1 FK).


0

어떤 이유로 두 직원 유형에 대해 두 개의 테이블이 있어야한다고 가정하면 vmarquez의 답변을 확장하겠습니다.

개요:

employees_ce (id, name)
employees_sn (id, name)
deductions (id, parentId, parentType, name)

공제 데이터 :

deductions table
id      parentId      parentType      name
1       1             ce              gold
2       1             sn              silver
3       2             sn              wood
...

이렇게하면 스키마의 다른 테이블을 차감 할 수 있습니다. 이러한 종류의 관계는 데이터베이스 수준 제약 조건 인 IIRC에서 지원되지 않으므로 앱이 제약 조건을 적절하게 관리하는지 확인해야합니다 (동일한 데이터베이스에 여러 앱 / 서비스가있는 경우 더 번거 로움).

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