0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SQLでの複数列ユニークインデクスにおけるNULLの挙動について

Posted at

SQLでユニーク制約を使用するとき、ANSI SQLではNULLを除いた値に対してユニーク制約がかかり、SQL ServerではNULLを含めてユニーク制約がかかることが知られています。この記事では、ユニーク制約のついた複数列インデクスにおけるNULLの挙動について見ていきます。

PostgreSQL

環境: PostgreSQL 12

CREATE TABLE table_two_col (
  col1 int, -- Nullable
  col2 int  -- Nullable
);
CREATE UNIQUE INDEX Idx_table_two_col_col1_col2 ON table_two_col (col1, col2);

INSERT INTO table_two_col (col1, col2) VALUES (1, 1);
INSERT INTO table_two_col (col1, col2) VALUES (1, 1); -- error
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL); -- OK
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL); -- OK

SELECT * FROM table_two_col;
-- col1,col2
-- 1,1
-- 1,NULL
-- 1,NULL
-- NULL,NULL
-- NULL,NULL

SQL Server

環境: SQL Server 2017

CREATE TABLE table_two_col (
  col1 int, -- Nullable
  col2 int -- Nullable
);
CREATE UNIQUE INDEX Idx_table_two_col_col1_col2 ON table_two_col (col1, col2);

INSERT INTO table_two_col (col1, col2) VALUES (1, 1);
INSERT INTO table_two_col (col1, col2) VALUES (1, 1); -- error
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL); -- error
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL); -- error

SELECT * FROM table_two_col;
-- col1,col2
-- NULL,NULL
-- 1,NULL
-- 1,1

SQL Serverで、Filtered IndexによりANSI SQLの動作を再現する場合

Filtered Index(フィルター選択されたインデックス)を使用することにより、ANSI SQLのユニークインデックスのNULLの挙動を再現する方法がよく使用されています。

CREATE TABLE table_two_col (
  col1 int, -- Nullable
  col2 int -- Nullable
);
CREATE UNIQUE INDEX Idx_table_two_col_col1_col2 ON table_two_col (col1, col2) WHERE col1 IS NOT NULL AND col2 IS NOT NULL; -- この行のWHERE以降の部分

INSERT INTO table_two_col (col1, col2) VALUES (1, 1);
INSERT INTO table_two_col (col1, col2) VALUES (1, 1); -- error
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (1, NULL); -- OK
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL);
INSERT INTO table_two_col (col1, col2) VALUES (NULL, NULL); -- OK

SELECT * FROM table_two_col;
-- col1,col2
-- 1,1
-- 1,NULL
-- 1,NULL
-- NULL,NULL
-- NULL,NULL
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?