답변:
왜 이런 식으로 작동합니까? 과거로 돌아가서 누군가가 표준이 말하는 것에 대해 알거나 신경 쓰지 않고 디자인 결정을 내 렸습니다 NULL
. 이 결정은 이 경우에 NULL = NULL
…
현명한 결정은 아니 었습니다. 그들이해야 할 일은 기본 동작이 ANSI 표준을 준수하는 것입니다.이 독특한 동작을 실제로 원한다면 WITH CONSIDER_NULLS_EQUAL
or 같은 DDL 옵션을 통해 허용하십시오 WITH ALLOW_ONLY_ONE_NULL
.
물론, 가늠자는 20/20입니다.
그리고 우리는 어쨌든 가장 깨끗하거나 직관적이지 않더라도 해결 방법을 가지고 있습니다.
필터링 된 고유 인덱스를 만들어 SQL Server 2008 이상에서 올바른 ANSI 동작을 얻을 수 있습니다.
CREATE UNIQUE INDEX foo ON dbo.bar(key) WHERE key IS NOT NULL;
NULL
이러한 행은 중복 검사에서 완전히 제외되므로 둘 이상의 값을 허용 합니다. 또한 보너스로 여러 NULL
개가 허용 된 경우 (특히 인덱스의 유일한 열이 아니고 열이있는 경우) 전체 테이블로 구성된 인덱스보다 작은 인덱스가 됩니다 INCLUDE
. 그러나 필터링 된 인덱스의 다른 제한 사항을 알고 싶을 수도 있습니다.
옳은. SQL Server에서 고유 제한 조건 또는 색인을 구현하면 하나의 NULL 만 허용됩니다. 또한 이것은 기술적으로 NULL의 정의와 맞지 않지만 "기술적으로"정확하지 않더라도 더 유용하게 만드는 것들 중 하나입니다. PRIMARY KEY (고유 인덱스)는 NULL을 허용하지 않습니다 (물론).
먼저 "Null value"라는 문구 사용을 중지하면 실수로 이어질 수 있습니다. 대신 "널 마커"라는 문구를 사용하십시오.이 컬럼의 실제 값이 누락되었거나 적용 할 수 없음을 나타내는 컬럼의 마커입니다 (그러나 마커는 이러한 옵션 중 실제로 어떤 옵션이 1인지 표시하지 않습니다).
이제 다음을 상상해보십시오 (데이터베이스에 모델링 된 상황에 대한 완전한 지식이없는 경우).
Situation Database
ID Code ID Code
-- ----- -- -----
1 A 1 A
2 B 2 (null)
3 C 3 C
4 B 4 (null)
우리가 모델링하는 무결성 규칙은 "코드는 고유해야합니다"입니다. 실제 상황이이를 위반하므로 데이터베이스는 항목 2와 4가 동시에 테이블에있는 것을 허용하지 않아야합니다.
가장 안전하고 융통성이없는 방법은 코드 필드에서 널 마커를 허용하지 않는 것이므로 데이터가 일치하지 않을 가능성이 없습니다. 가장 유연한 방법은 여러 개의 null 마커를 허용하고 값을 입력 할 때 고유성에 대해 걱정하는 것입니다.
Sybase 프로그래머는 테이블에 하나의 널 마커 만 허용하는 다소 안전하고 유연하지 않은 접근 방식을 사용했습니다. Microsoft는이 동작을 계속했으며 이전 버전과의 호환성을 기대합니다.
¹ 나는 Codd가 두 개의 널 마커 (알 수없는 마커, 적용 할 수없는 마커)의 구현을 고려했지만 거부했지만 어쨌든 참조를 찾을 수 없다고 확신합니다. 내가 올바르게 기억하고 있습니까?
추신 : null에 대해 내가 가장 좋아하는 인용문 : Louis Davidson, "Professional SQL Server 2000 데이터베이스 디자인", Wrox Press, 2001, 페이지 52. "한 문장으로 마무리 : NULL은 악입니다."
null
목표를 달성 할 수 없습니다. 결 측값이 다른 행 중 하나의 값과 같을 수 있기 때문입니다.
CHECK (Value IN ('A','B','C','D'))
합니까? 그런 다음 SQL-Server의 구현과 SQL 표준 모두 테이블에 5 개의 행 (각 값에 대해 한 행에 NULL이있는 1을 더한 값)을 가질 수 있도록합니다. 그런 다음 데이터베이스는 제약 조건과 일치하지만 디자이너의 의도와 일치하지 않습니다. 최대 4 행의 테이블. 하나 이상의 행이 삭제되지 않는 한 제약 조건을 위반하지 않는 NULL로 변경할 수있는 값은 없습니다.
CREATE TABLE #T(A INT NULL UNIQUE);INSERT INTO #T VALUES (1),(NULL);UPDATE #T SET A = 1 WHERE A IS NULL;
오류가 발생합니다. NULL
불완전한 지식은 가치가 다르다는 것을 보장하지 않기 때문에 디자인 동기에 대한 이론에 따르면 첫 번째 경우에 삽입을 막아야했을 것입니다.
이것은 기술적으로 정확하지는 않지만 철학적으로 밤에 잠을 자는데 도움이됩니다 ...
다른 사람들이 말했거나 암시 한 것처럼 NULL을 알 수없는 것으로 생각하면 하나의 NULL 값이 실제로 다른 NULL 값과 같은지 여부를 결정할 수 없습니다. 이런 식으로 생각하면 NULL == NULL 표현식은 NULL로 평가되어야합니다.
고유 제한 조건은 열 값을 비교하기 위해 결정적인 값이 필요합니다. 즉, 항등 연산자를 사용하여 단일 열 값을 다른 열 값과 비교할 때 유효하려면 false로 평가해야합니다. 알 수없는 경우가 종종 허위로 취급 되더라도 실제로는 거짓이 아닙니다. 두 개의 NULL 값은 같거나 같지 않을 수 있습니다. 단순히 결정하기가 어렵습니다.
고유 제한 조건을 서로 구별 할 수있는 값을 제한하는 것으로 생각하면 도움이됩니다. 이것이 의미하는 바는 다음과 같은 SELECT를 실행하는 것입니다.
SELECT * from dbo.table1 WHERE ColumnWithUniqueContraint="some value"
고유 한 제약 조건이있는 경우 대부분의 사람들은 하나의 결과를 기대합니다. ColumnWithUniqueConstraint에서 여러 개의 NULL 값을 허용 한 경우 비교 값으로 NULL을 사용하여 테이블에서 하나의 고유 한 행을 선택할 수 없습니다.
따라서 NULL 정의와 관련하여 정확하게 구현되었는지 여부에 관계없이 여러 NULL 값을 허용하는 것보다 대부분의 상황에서 훨씬 더 실용적이라고 생각합니다.
UNIQUE
제약 조건 의 주요 목적 중 하나는 중복 레코드를 방지하는 것입니다. 값을 "알 수없는"여러 레코드가있을 수있는 테이블이 필요하지만 두 레코드가 동일한 "알려진"값을 가질 수없는 경우 알 수없는 값에는 인공 고유 식별자를 할당해야합니다. 테이블에 추가되었습니다.
UNIQUE
제약 조건이 있고 단일 null 값을 포함하는 열이 드문 경우가 몇 가지 있습니다. 예를 들어, 테이블에 열 값과 현지화 된 텍스트 설명 간의 매핑이 포함 된 경우 행 NULL
을 사용하면 다른 테이블의 해당 열이 일 때 표시 될 설명을 정의 할 수 있습니다 NULL
. 동작에 NULL
따라 해당 사용 사례 가 허용됩니다.
그렇지 않으면 UNIQUE
동일한 레코드가 많이 존재할 수 있도록 열에 제약 조건이 있는 데이터베이스에 대한 근거가 없지만 키 값을 구별 할 수없는 여러 레코드를 허용하면서이를 막을 방법이 없습니다. NULL
그 자체와 같지 않다고 선언 하면 NULL
값을 서로 구별 할 수 없습니다 .