전이 외래 키를 추가해야합니까?


11

간단한 예 : 고객 테이블이 있습니다.

create table Customers (
  id integer,
  constraint CustomersPK primary key (id)
)

데이터베이스의 다른 모든 데이터는에 연결되어야합니다. Customer예를 들면 Orders다음과 같습니다.

create table Orders (
  id integer,
  customer integer,
  constraint OrdersPK primary key (customer, id),
  constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)

이제 연결되는 테이블이 있다고 가정하십시오 Orders.

create table Items (
  id integer,
  customer integer,
  order integer,
  constraint ItemsPK primary key (customer, id),
  constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)

나는로부터 별도의 외부 키를 추가해야 Items하는 Customers?

...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)

사진 대신 : 점선 / FK를 추가해야합니까?

간단한 예제 스키마


편집 : 기본 키 정의를 테이블에 추가했습니다. 위에서 언급 한 요점을 다시 반복하고 싶습니다. 데이터베이스는 기본적으로 정확성 / 보안 수단으로 고객이 보관합니다. 따라서 모든 기본 키에는 customerID가 포함 됩니다.


2
아닙니다. 추가 FK가 필요하지 않습니다. 제약 조건은 다른 두 FK에 의해 시행됩니다.
ypercubeᵀᴹ

@ypercube 리던던트 FK를 사용하는 경우 성능 저하가 있습니까? 당신이 생각할 수있는 어떤 이점이 있습니까? ...
vektor

1
@vektor에서 성능 측면은 아마도 rdbms마다 다를 수 있지만 일반적으로 PK / FK 테이블 중 하나의 모든 삽입 / 업데이트 / 삭제는 다음에 대해 검사해야하기 때문에 추가하는 새로운 FK마다 성능에 영향을 미칩니다. 강제. 큰 PK 테이블을 사용하면이 성능 저하가 상당히 심할 수 있습니다.
Daniel Hutmacher

답변:


6

이것이 원래 생각이라고 생각합니다.

여기에 이미지 설명을 입력하십시오

첫 번째로 주목해야 할 것은 LineItem 테이블의 PK에는 세 개의 속성이 {CustomerID, CustomerOrderNo, OdrerItemNo}있지만,이 예제에서는 단지 두 개의 속성이 없습니다 .

두 번째로 주목해야 할 것은 id속성에 일반 이름을 사용하여 발생하는 혼란 입니다.

CustomerOrderNo이상적 (1,2,3 ..) 각 고객 및 대한이어야한다 OrderItemNo각 순서 (1,2,3 ...).

글쎄, 이것은 가능하다면 좋지만 이전과 같은 최대 값을 찾는 쿼리가 필요합니다.

select max(CustomerOrderNo)
from Order 
where CustomerID = specific_customer ; 

트랜잭션 볼륨이 큰 환경에서는 선호되지 않는 경우가 많으므로 기본적으로 동일한 목적을 수행하는 자동 증가로 대체되는 것이 일반적입니다. 이 자동 증가는 이제 독창적이므로 KEY로 사용할 수 있습니다. 그러나 OrderItemNo.

그래서, 일부는 이름 바꾸기로 CustomerOrderNo -> OrderNo하고 OrderItemNo-> ItemNo당신은이 모델에 도착할 수있다

여기에 이미지 설명을 입력하십시오

이제 Order다음 을 보면 고유합니다.

{OrderNo}             -- PK
{CustomerID, OrderNo} -- superkey,  AK on the diagram.

참고 {CustomerID, OrderNo}받는 전파는 LineItemFK 역할을합니다.

약간 곁눈질하는 경우 이는 예제와 비슷하지만 예제의 PKs {ItemNo} and {OrderNo}두 열 PK와는 반대입니다.

이제 질문은 왜 이런 식으로 단순화하지 않습니까?

여기에 이미지 설명을 입력하십시오

어떤 괜찮지 만 소개합니다 경로 의존성 - 당신은 가입 할 수 없습니다 LineItemCustomer직접 사용해야합니다 Order조인에.


가능한 경우 첫 번째 경우를 선호합니다. 좋아하는 것을 선택하십시오. 그리고 분명히이 세 가지 경우 에 직접 FK를 전환 LineItem할 필요가 없습니다 Customer.


나는 주변을 둘러 보았지만 "경로 의존성"이 내가 "2 차 전이 관계"(내 용어가 틀렸을지라도)라고하는 것에 대해 널리 채택 된 용어로 사용되는 것을 볼 수 없다
Dai

2

"아이템"은 "고객"을 직접 참조해서는 안됩니다. 이는 아이템의 "주문"에 의해 암시되기 때문입니다. 따라서 "항목"테이블에 "고객"열이 전혀 필요하지 않습니다.

기존 외래 키를 통해 품목과 고객의 관계가 보장됩니다.

orders.id가 ID 열인 경우 items.customer를 모두 제거하십시오.


1
감사합니다. "고객"이 "항목"에서 "주문"까지 첫 번째 FK에 포함 된 것을 알지 못했습니다. 나는 이에 따라 정답을 정교화했다.
다니엘 헛 마허

@DanielHutmacher 테이블의 기본 키를 포함하도록 질문을 편집했습니다. 이것은 편집에서 언급 한 이상한 FK를 설명합니다.
vektor

좋아, 나는 대답을 업데이트했다. :)
Daniel Hutmacher

나는 customer모든 테이블에 (따라서 DB를 사일로 화하는) 것은 드문 접근법이라고 생각합니다. 이전 작품에서 본 것임을 고백해야합니다. 당신에게 어떤 의미가 있습니까? 그런 디자인을 본 적이 있습니까?
vektor

조인을 제거하기 위해 의도적으로 데이터를 비정규 화하려는 데이터웨어 하우스 (스타 스키마) 접근 방식처럼 보입니다. 또는 기본 키는 주문 ID 열만 고유하지 않은 경우 고객 A의 첫 번째, 두 번째, 세 번째 주문, 고객 B의 첫 번째, 두 번째 주문 등과 같이 복합적 일 수 있습니다.
Daniel Hutmacher
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.