Nullable Foreign Key 나쁜 습관?


114

고객 ID에 대한 외래 키가있는 주문 테이블이 있다고 가정 해 보겠습니다. 이제 고객 ID없이 주문을 추가하고 싶다고 가정합니다. (가능할지 여부는 다른 질문입니다.) 외래 키를 NULL로 만들어야합니다 ... 그게 나쁜 습관인가요 아니면 차라리 주문 및 고객? 관계가 1에서 n이지만 링크 테이블은 n에서 n으로 만듭니다. 반면에 링크 테이블을 사용하면 더 이상 NULL이 없습니다.

NULL에 대한 외래 키가있는 레코드는 주문에 대한 고객이 추가 될 때까지 일시적이기 때문에 실제로 데이터베이스에 NULL이 많지 않습니다.

(제 경우에는 주문 및 고객이 아닙니다).

편집 : 연결할 할당되지 않은 고객은 어떻습니까?


9
이는 데이터베이스 스키마에서 NULL을 사용할 수있는 주요 목적 중 하나입니다. 또한 스키마의 특정 요구 사항을 충족 할 수 있도록 필드 NULL 또는 NOT NULL을 선언 할 수 있습니다.
gahooa 2009

7
나는 처음에 Nullable Primary keys 로 질문을 읽었고 강력한 조언을하려고했습니다 ... :-)
Andrzej Doyle

답변:


51

링크 테이블을 갖는 것이 아마도 더 나은 옵션 일 것입니다 . 적어도 정규화 BCNF (Boyce-Codd 정규형)를 위반하지 않습니다 . 그러나 나는 실용적인 것을 선호합니다. 이러한 null 값이 거의없고 일시적인 경우 스키마에 복잡성을 추가 할 뿐이므로 링크 테이블을 건너 뛰어야한다고 생각합니다.

참고로, 링크 테이블을 사용한다고해서 반드시 n 대 n이되는 것은 아닙니다. 링크 테이블에서 주문 테이블을 가리키는 외래 키를 해당 링크 테이블의 기본 키로 사용하는 경우 관계는 여전히 1..n입니다. 해당 링크 테이블에는 주문 당 하나의 항목 만있을 수 있습니다.


2
source__destination_link 또는 SourceDestination
Svisstack 2012 년

7
링크 테이블이 더 좋은 상황에 대해 듣고 싶습니다. 어떤 식 으로든 프로세스 흐름을 개선 할 수있는 상황에 처한 적이 없습니다.
Reimius

5
내 대답에서 지적 했듯이이 특정 경우에는 실용적이며 링크 테이블을 사용하지 않습니다. 정상적인 형태는 프로세스 흐름을 개선하기 위해 고안된 것이 아니라 일관성을 보장하고 중복을 피하기 위해 고안된 것입니다. 하지만 이것은 매우 일반적인 논의이지만, 사례별로 살펴 봐야한다고 생각합니다.
패트릭 Hägne

110

Nullable FK에는 문제가 없습니다. 이는 FK가 가리키는 엔터티가 기본 키 참조 테이블과 (0 또는 1) 대 (1 또는 다수) 관계에있을 때 일반적입니다.

예를 들어 주소 테이블에 대한 FK가있는 테이블에 물리적 주소와 우편 주소 속성 (열)이 모두있는 경우가 있습니다. 엔티티에 우체국 상자 (우편 주소) 만있는 경우 처리하기 위해 물리적 주소를 nullable로 만들 수 있고, 우편 주소가 실제 주소와 같거나 같지 않을 때 처리 할 수 ​​있도록 우편 주소를 nullable로 만들 수 있습니다.


39

Nullable 열은 1NF ~ 5NF에있을 수 있지만 내가 읽은 내용에 따라 6NF에는있을 수 없습니다.

Chris Date보다 "첫 번째 정규 형식이 실제로 무엇을 의미하는지"를 더 잘 아는 경우에만. x와 y가 일부 행의 x 실제로 모두 Null을 허용하고 있습니다와 y가 모두있는 경우 null, 다음 WHERE x=y양보하지 않습니다 true. 이것은 null이 값이 아님을 합리적인 의심의 여지없이 증명합니다 (실제 값은 항상 자신과 동일하기 때문입니다). 그리고 RM은 "테이블의 모든 셀에 값이 있어야한다"라고 규정하고 있기 때문에 null을 포함 할 수있는 것은 관계형이 아니므로 1NF에 대한 질문도 발생하지 않습니다.

일반적으로 Nullable 열이 첫 번째 정규화 수준을 깨뜨린다는 주장을 들었습니다.

그 주장의 근거가되는 건전한 이유는 위를 참조하십시오.

그러나 실제로는 매우 실용적입니다.

일반적으로 전 세계에서 발생하는 두통에 면역이있는 경우에만 가능합니다. 그러한 골칫거리 중 하나 (그리고 다른 null현상에 비해 사소한 문제 일뿐입니다 )는 WHERE x=ySQL에서 실제로는을 의미 WHERE x is not null and y is not null and x=y하지만 대부분의 프로그래머는 그 사실을 인식하지 못하고 그냥 읽는다는 사실입니다. 때로는 아무런 해를 끼치 지 않고 다른 때는 그렇지 않습니다.

실제로 nullable 열은 가장 기본적인 데이터베이스 디자인 규칙 중 하나를 위반합니다. 하나의 열에 고유 한 정보 요소를 결합하지 마십시오. Null은 부울 값 "이 필드가 실제로 존재하지 않음"을 실제 값과 결합하기 때문에 정확히 수행합니다.


18
"WHERE x가 널이 아니고 y가 널이 아니고 x = y"에 대해 +1. 그것을 인식하지 못했습니다.
RobM

1
논쟁과 예를 아주 잘 정리했습니다.
pedz

1
하나의 문제. 값이 "존재하지 않음"(실제 시나리오 임)이고 데이터베이스 속성이 널을 허용하지 않는 경우 속성에있는 모든 값은 WRONG입니다. 두통에 관해서는, KISS를 기억하십시오. 그것은 단순히 단순하게 유지하는 것을 의미하는 것이 아니라 가능한 한 단순하게 유지하는 것을 의미합니다. "관계형 모델"이 비현실적이고 어리석은 결과를 필요로한다면 필요한 실제 데이터를 처리하기 위해 규칙을 확장해야할까요?
Charles Bretana

1
3 값 논리는 4 값 논리를 필요로하고, 5 값 논리 등이 필요하다는 것이 밝혀졌습니다. 2 값 논리 이면 충분하지만, 우리가 얻을 수있는 데이터 구조는 그것을 적용하면 "가능한 한 간단하게"는 "우리가 원하는대로 간단하게"하는 것보다 훨씬 덜 간단합니다.
Erwin Smout

2
Chris Date, Logic & Databases, 6 장, "관계형 DBMS 논리가 많은 가치를 가져서는 안되는 이유", 페이지 145. 해당 장에 대한 참조 목록, 특히 McGoveran과 관련된 참조 목록도 흥미로워 야합니다.
Erwin Smout

13

외래 키에서 null로 표시되는 선택적 n-1 관계라는 점에서 잘못된 점을 볼 수 없습니다. 그렇지 않으면 링크 테이블을 넣으면 nn 관계가되지 않도록 관리해야하므로 더 많은 문제가 발생합니다.


2
실제로 이것은 선택적인 1-N 관계가 아니라 0-N 관계입니다. 하지만 동의합니다.
Eric J.

5
꾸리다? 0 대 1 측면에 대한 간단한 UNIQUE 제약 조건입니다!
wqw 2009

2
예, UNIQUE 제약 조건이지만 나중에 코드에서 해당 제약 조건으로 인해 가능한 예외를 처리해야합니다.
pedromarce 2009

4

선택적 관계는 관계형 모델에서 확실히 가능합니다.

널을 사용하여 관계의 부재를 표현할 수 있습니다. 그들은 편리하지만 null이 다른 곳에서 발생하는 것과 동일한 두통을 유발할 것입니다. 문제를 일으키지 않는 한 곳은 조인입니다. 외래 키에 null이있는 행은 참조 된 테이블의 어떤 행과도 일치하지 않습니다. 그래서 그들은 내부 결합에서 탈락합니다. 외부 조인을 수행하면 어쨌든 null을 처리하게됩니다.

정말로 널 (6 번째 정규형)을 피하려면 테이블을 분해 할 수 있습니다. 분해 된 두 테이블 중 하나에 두 개의 외래 키 열이 있습니다. 하나는 가지고있는 선택적 외래 키이고 다른 하나는 원래 테이블의 기본 키를 참조하는 외래 키입니다. 이제 제약 조건을 사용하여 관계가 다대 다가되는 것을 방지해야합니다.


2

NULL을 사용하는 것은 불완전한 주문을 정리하는 좋은 방법입니다.

SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL

위의 내용은 관련 고객 ID없이 15 분 이상 지난 주문을 보여줍니다.


1

고객이 정의 될 때까지 고객 ID없이 일시적으로 주문을 추가하는 경우 단일 트랜잭션에서 고객 및 주문을 추가하는 것이 더 간단하지 않아 NULL 외래 키 입력의 필요성을 제거하고 제약이나 트리거를 피할 수 있습니다. 당신은 위반을 설정 했습니까?

일반적으로 이러한 상황은 고객이 자신이 누구인지 정의하기 전에 주문을 자세히 설명하는 웹 앱에서 발생합니다. 그리고 이러한 상황에서는 주문이 데이터베이스에 유지되는 시점에서 전체 주문에 필요한 모든 상태가 제공 될 때까지 주문이 서버 상태 또는 쿠키에 보관됩니다.

NULL 외래 키는 위에서 언급했듯이 주소와 같은 항목에 적합합니다. 그러나 NULL 고객 필드는 주문에 적합하지 않으며 제한되어야합니다.


주문 고객이 한 예였습니다. 내 앱에서는 주소와 비슷합니다. 올바른 예를 즉시 찾을 수 없었습니다. 고마워.
Lieven Cardoen 2009

1
이것은 데이터베이스가 장바구니에 항목을 저장하는 데 사용되는 경우 유효한 시나리오가 될 수 있습니다. 여기서 장바구니는 등록 된 사용자에게 속하지 않습니다.
Johnie Karr 2013

1

항상 Id = -1 및 CustomerName = 'Unknown'과 같은 인공 행을 Customer 테이블에 추가 할 수 있으며 일반적으로 Order NULL에서 CustomerId를 설정하는 경우에는 -1로 설정합니다.

이를 통해 nullable FK는 없지만 데이터 부족을 적절하게 나타낼 수 있습니다 (그리고 NULL을 처리하는 방법을 모르는 다운 스트림 사용자로부터 사용자를 구할 수 있습니다).


여기에 추가하기 위해 NULLS는 인덱스 (오라클)에 저장되지 않으므로 링크 테이블을 건너 뛰고 nullable FK로 이동하는 것이 성능면에서 의미가 있음을 의미합니다. 다른 하나는이 링크 테이블에 다른 것을 저장하려는 경우입니다. 예를 들어, 누가 링크를 만들었고 언제? 링크가 현재 비활성화 / 삭제 되었습니까 (한 번은 삭제 되었습니까?)
Worthy7

이것은 나쁜 생각입니다. 설정된 외래 키가 있고 가리키는 데이터가 나중에 제거되면 외래 키 예외가 발생하지 않으며 이제 데이터가 무의미합니다. 더 나쁜 것은, 뭔가 나중에 완전히 잘못된 고객에게 가리키고 해당 키에 할당에있는 경우
IcedDante

0

선택적 다 대일 관계에 대한 Nullable FK는 완전히 괜찮습니다.


-1

일반적으로 Nullable 열이 정규화의 첫 번째 수준을 위반한다고 주장하는 것을 들었습니다. 그러나 실제로는 매우 실용적입니다.


3
Nullable 열은 1NF ~ 5NF에있을 수 있지만 내가 읽은 내용에 따라 6NF에는있을 수 없습니다.
Walter Mitty

-1

예, 뭔가 잘못되었습니다. nullable 경우 외래 키가 아닙니다. 코드에 의한 데이터베이스 디자인. 할당되지 않은 링크를 0으로 만들 수도 있습니다. 또는 문자 col을 사용하는 경우 "Unassigned". 데이터의 무결성을 100 % 유지하십시오.

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