답변:
기본 키는 행을 고유하게 식별하기위한 것입니다. 이것은 키의 모든 부분을 입력과 비교하여 수행됩니다.
정의에 따라 NULL은 성공적인 비교의 일부가 될 수 없습니다. 자체 비교 ( NULL = NULL
)도 실패합니다. 이는 NULL을 포함하는 키가 작동하지 않음을 의미합니다.
또한 외래 키에서는 NULL을 사용하여 선택적 관계를 표시 할 수 있습니다. (*) PK에서도 허용하면이 문제가 발생합니다.
(*) 주의 사항 : 널 입력 가능 외래 키를 갖는 것은 관계형 데이터베이스 설계가 깨끗하지 않습니다.
이 두 개의 엔티티 인 경우 A
와 B
위치를 A
선택적으로 관련 될 수있다 B
, 깨끗한 솔루션은 해상도 테이블을 만드는 것입니다 (의 말을하자 AB
). 그 표는 연결 것 A
으로 B
:이 경우 입니다 관계가 있다면 그것은, 기록을 포함하는 것 아니다 는 않을 것 다음.
기본 키는 테이블의 모든 행에 대한 고유 식별자를 정의 합니다. 테이블에 기본 키가 있으면 원하는 행을 선택할 수 있습니다.
고유 제한 조건이 반드시 모든 행을 식별하지는 않습니다. 그냥하도록 지정 하면 행이 컬럼의 값을 가지고, 다음, 그들이 고유해야합니다. 이것은 모든 행 을 고유하게 식별하기에는 충분하지 않으므로 기본 키가 수행해야합니다.
기본적으로 다중 열 기본 키의 NULL에는 아무런 문제가 없습니다. 그러나 디자이너가 의도하지 않은 의미를 갖는 것은 많은 시스템이 오류를 발생시키는 이유입니다.
일련의 필드로 저장된 모듈 / 패키지 버전의 경우를 고려하십시오.
CREATE TABLE module
(name varchar(20) PRIMARY KEY,
description text DEFAULT '' NOT NULL);
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20),
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
기본 키의 처음 5 개 요소는 정기적으로 릴리스 버전의 일부로 정의되지만 일부 패키지는 일반적으로 정수가 아닌 사용자 정의 된 확장명 (예 : "rc-foo"또는 "vanilla"또는 "beta"또는 기타 다른 것)을 갖습니다. 누구 네 개의 필드은) 꿈을 꿀 수도 부족하다. 패키지에 확장명이 없으면 위의 모델에서 NULL이며, 그렇게 놔두면 아무런 해가 없습니다.
그러나 NULL 은 무엇 입니까? 그것은 정보 의 부족 , 알 수없는 것으로 나타납니다 . 즉, 아마도 이것이 더 의미가 있습니다.
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20) DEFAULT '' NOT NULL,
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
이 버전에서 튜플의 "ext"부분은 NULL이 아니지만 기본값은 비어있는 문자열입니다. 이는 의미 상 (실제로는) NULL과 다릅니다. 빈 문자열은 "무엇이 존재하지 않는지"고의로 기록한 반면 NULL은 알 수 없습니다. 다시 말해, "빈"과 "널"은 다른 것입니다. "여기에 가치가 없습니다"와 "여기에 가치가 무엇인지 모르겠습니다."의 차이점이 있습니다.
버전 확장이없는 패키지를 등록하면 확장이 없다는 것을 알고 있으므로 빈 문자열이 실제로 올바른 값입니다. NULL은 확장명이 있는지 여부를 모르거나 그것이 무엇인지 알았지 만 모르는 경우에만 정확합니다. 문자열 값이 표준 인 시스템에서는이 상황을 다루기가 더 쉽습니다. 0 또는 1을 삽입하는 것 이외의 "빈 정수"를 나타내는 방법이 없기 때문에 나중에 비교할 때 롤업됩니다. 자체 의미) *.
우연히도 Postgres에서는 두 가지 방법이 모두 유효하지만 ( "엔터프라이즈"RDMBS에 대해 논의하고 있기 때문에) NULL을 믹스에 넣을 때 비교 결과가 약간 다를 수 있습니다. 알려지지 않은 것을 알 수 없으므로 NULL을 포함하는 비교 결과가 NULL입니다. 위험! 이것에 대해 신중하게 생각하십시오. 이것은 NULL 비교 결과 가 일련의 비교를 통해 전파됨 을 의미합니다 . 이것은 정렬, 비교 등의 미묘한 버그의 원인이 될 수 있습니다.
Postgres는 귀하가 성인이라고 가정하고 스스로 결정할 수 있습니다. Oracle과 DB2는 당신이 어리석은 짓을하고 있다는 것을 몰랐으며 오류를 던졌다 고 가정합니다. 이것은 일반적 으로 올바른 일이지만 항상 그런 것은 아닙니다 . 어떤 경우에는 실제로 알지 못하고 NULL을 가질 수 있으므로 의미있는 비교가 불가능한 알 수없는 요소가있는 행을 남기는 것이 올바른 동작입니다.
어쨌든 전체 스키마에서 허용하는 NULL 필드 수를 제거하고 기본 키의 일부인 필드에 대해서는 이중으로 제거해야합니다. 대부분의 경우 NULL 열의 존재는 정규화되지 않은 (고의적으로 비정규 화되지 않은) 스키마 설계를 나타내며 허용되기 전에 매우 열심히 생각해야합니다.
[* 참고 : 정수와 "알 수 없음"과 의미 적으로 "빈"을 의미하는 "하단"형식의 조합 인 사용자 지정 형식을 만들 수 있습니다. 불행히도 이것은 비교 연산에 약간의 복잡성을 초래하며 일반적으로 실제로 유형이 정확하다는 것은 실제로 많은 노력을 기울일 가치가 없으므로 NULL
처음에는 많은 가치를 허용해서는 안됩니다 . 즉, RDBMS 에 "값 없음"의 의미를 "알 수없는 값"으로 자연스럽게 병합하는 습관을 방지하는 BOTTOM
것 외에도 기본 유형을 포함하는 것이 좋을 것 NULL
입니다. ]
NULL == NULL-> false (적어도 DBMS에서는)
따라서 실제 값이있는 추가 열이있는 경우에도 NULL 값을 사용하여 관계를 검색 할 수 없습니다.
where pk_1 = 'a' and pk_2 = 'b'
에는 정상 값을 사용 하고 where pk_1 is null and pk_2 = 'b'
널이있을 때 전환 할 수 있습니다 .
where (a.pk1 = b.pk1 or (a.pk1 is null and b.pk1 is null)) and (a.pk2 = b.pk2 or (a.pk2 is null and b.pk2 is null))
/
Tony Andrews의 답변은 괜찮습니다. 그러나 진정한 대답은 이것이 관계형 데이터베이스 커뮤니티에서 사용하는 규칙이었으며 필수는 아니라는 것입니다. 어쩌면 좋은 컨벤션 일 수도 있고 아닐 수도 있습니다.
NULL과 비교하면 UNKNOWN (3 진값)이됩니다. 따라서 null로 제안 된 것처럼 평등에 관한 모든 전통적 지혜가 창 밖으로 나옵니다. 그것이 언뜻보기에 그렇게 보입니다.
그러나 이것이 반드시 그렇게 생각하지는 않으며 SQL 데이터베이스조차도 NULL이 비교의 모든 가능성을 파괴한다고 생각하지 않습니다.
데이터베이스에서 SELECT * FROM VALUES (NULL) 쿼리를 실행하십시오. UNION SELECT * FROM VALUES (NULL)
당신이 보는 것은 NULL 값을 가진 하나의 속성을 가진 하나의 튜플입니다. 따라서 유니온은 여기서 두 개의 NULL 값을 동일한 것으로 인식했습니다.
3 개의 구성 요소가있는 복합 키를 3 개의 속성 (1, 3, NULL) = (1, 3, NULL)을 갖는 튜플과 비교할 때 <=> 1 = 1 AND 3 = 3 AND NULL = NULL이 결과는 알 수 없음 .
그러나 우리는 새로운 종류의 비교 연산자를 정의 할 수 있습니다. ==. X == Y <=> X = Y OR (X IS NULL AND Y IS NULL)
이러한 종류의 항등 연산자가 있으면 null 구성 요소가있는 복합 키 또는 null 값이있는 비 복합 키를 문제가되지 않습니다.