[database-design] Nullable Foreign Key 나쁜 습관?

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

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

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

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



답변

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

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


답변

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

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


답변

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은 부울 값 “이 필드가 실제로 존재하지 않음”을 실제 값과 결합하기 때문에 정확히 수행합니다.


답변

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


답변

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

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

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


답변

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

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

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


답변

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

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

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