programing

NULL 열에 고유 인덱스를 만드는 방법은 무엇입니까?

showcode 2023. 6. 4. 10:43
반응형

NULL 열에 고유 인덱스를 만드는 방법은 무엇입니까?

SQL Server 2005를 사용하고 있습니다.NULLS를 허용하면서 열의 값이 고유하도록 제한하려고 합니다.

현재 솔루션에는 다음과 같은 관점에서 고유한 인덱스가 포함됩니다.

CREATE VIEW vw_unq WITH SCHEMABINDING AS
    SELECT Column1
      FROM MyTable
     WHERE Column1 IS NOT NULL

CREATE UNIQUE CLUSTERED INDEX unq_idx ON vw_unq (Column1)

더 좋은 생각은 없습니까?

SQL 서버 2008을 사용하여 필터링된 인덱스를 생성할 수 있습니다.

CREATE UNIQUE INDEX AK_MyTable_Column1 ON MyTable (Column1) WHERE Column1 IS NOT NULL

다른 옵션은 고유성을 검사하는 트리거이지만 성능에 영향을 줄 수 있습니다.

계산된 칼럼 트릭은 "널버스터"로 널리 알려져 있습니다. 제 노트에는 Steve Kass가 있습니다.

CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X  int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)

그것은 독특한 목적에 위배되기 때문에 당신은 그렇게 할 수 없다고 꽤 확신합니다.

하지만, 이 사람은 괜찮은 일거리가 있는 것 같습니다: http://sqlservercodebook.blogspot.com/2008/04/multiple-null-values-in-unique-index-in.html

필터 술어를 사용하여 인덱스에 포함할 행을 지정할 수 있습니다.

설명서에서 다음을 참조하십시오.

WHERE <filter_predicate> 인덱스에 포함할 행을 지정하여 필터링된 인덱스를 만듭니다.필터링된 인덱스는 테이블의 비클러스터형 인덱스여야 합니다.필터링된 인덱스의 데이터 행에 대한 필터링된 통계를 생성합니다.

예:

CREATE TABLE Table1 (
  NullableCol int NULL
)

CREATE UNIQUE INDEX IX_Table1 ON Table1 (NullableCol) WHERE NullableCol IS NOT NULL;

엄밀히 말하면, 고유한 null 가능 열(또는 열 집합)은 동일한 값(NULL 포함)을 두 번 이상 갖는 것은 고유 제약 조건을 명백히 위반하기 때문에 한 번만 NULL(또는 NULL 레코드)일 수 있습니다.

그러나, 그것이 "고유의 nullable column"이라는 개념이 유효하다는 것을 의미하지는 않습니다. 관계형 데이터베이스에서 실제로 구현하기 위해서는 이러한 종류의 데이터베이스가 제대로 작동하도록 정규화되어야 한다는 것을 명심해야 합니다.그리고 정규화에는 일반적으로 엔티티 간의 관계를 설정하기 위해 여러 개의 (비정규화) 추가 테이블이 포함됩니다.

하나의 "고유한 null 가능 열"만 고려한 기본 예제를 사용해 보겠습니다. 이러한 열을 더 많은 열로 확장하는 것은 쉽습니다.

다음과 같은 표로 표시되는 정보를 가정해 보겠습니다.

create table the_entity_incorrect
(
  id integer,
  uniqnull integer null, /* we want this to be "unique and nullable" */
  primary key (id)
);

유니크널을 분리하고 두 번째 테이블을 추가하여 유니크널 값과 _entity 사이의 관계를 설정할 수 있습니다.

create table the_entity
(
  id integer,
  primary key(id)
);

create table the_relation
(
  the_entity_id integer not null,
  uniqnull integer not null,

  unique(the_entity_id),
  unique(uniqnull),
  /* primary key can be both or either of the_entity_id or uniqnull */
  primary key (the_entity_id, uniqnull), 
  foreign key (the_entity_id) references the_entity(id)
);

uniquenull 값을 _entity의 행에 연결하려면 _relation에 행을 추가해야 합니다.

_entity의 행에 고유한 null 값이 연결되지 않은 경우(즉, _entity_incorrect에 NULL을 입력한 행의 경우) _relation에 행을 추가하지 않습니다.

uniqunull의 값은 모든_relation에 대해 고유하며 _entity의 각 값에 대해 최대 하나의 값이 있을 수 있습니다. 이는 기본 키와 외부 키가 이를 적용하기 때문입니다.

그런 다음 uniquenull에 대한 값 5를 _entity id 3과 연결하려면 다음을 수행해야 합니다.

start transaction;
insert into the_entity (id) values (3); 
insert into the_relation (the_entity_id, uniqnull) values (3, 5);
commit;

또한 _entity에 대한 id 값 10에 고유한 대응물이 없는 경우 다음 작업만 수행합니다.

start transaction;
insert into the_entity (id) values (10); 
commit;

이 정보를 비정규화하고 _entity_incorrect와 같은 테이블이 보유하는 데이터를 얻으려면 다음을 수행해야 합니다.

select
  id, uniqnull
from
  the_entity left outer join the_relation
on
  the_entity.id = the_relation.the_entity_id
;

"왼쪽 외부 조인" 연산자는 _entity의 모든 행이 결과에 나타나도록 하고, _relation에 일치하는 열이 없을 때 고유 null 열에 NULL을 넣습니다.

잘 정규화된 데이터베이스(및 그에 상응하는 비정규화된 보기 및 절차)를 설계하는 데 며칠(또는 몇 주 또는 몇 개월)의 노력을 기울이면 수년(또는 수십 년)의 고통과 낭비되는 리소스를 절약할 수 있습니다.

언급URL : https://stackoverflow.com/questions/191421/how-to-create-a-unique-index-on-a-null-column

반응형