【MySQL】UNIQUE制約 - カラムのユニーク(一意)化
MySQLのUNIQUE制約について解説します。
検証環境
UNIQUE制約
UNIQUE制約は“カラムの値を一意に保つ制約”です。
任意のカラムに設定でき、複数のカラムの組み合わせにすることも可能です。
この制約を設定したカラムの値は重複できず、インデックスが自動で作成されます。
主キーのPRIMARY KEY制約と似ていますが、使用目的が異なります。
また、PRIMARY KEY制約は値のNULLが許可されませんが、UNIQUEはNULLの設定が可能です。
単体カラム
単体カラムにUNIQUE制約を設定できます。
基本構文
カラム定義 UNIQUE
カラム定義に続いて、UNIQUE
を記述します。
サンプル
mysql> /* テーブル作成 */
mysql> CREATE TABLE items (
-> id INT UNIQUE,
-> name VARCHAR(20),
-> price INT,
-> stock INT
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> /* テーブル情報 */
mysql> DESC items;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
| price | int | YES | | NULL | |
| stock | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
mysql> /* インデックス確認 */
mysql> SHOW INDEX FROM items;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| items | 0 | id | 1 | id | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.00 sec)
mysql> /* レコード追加 */
mysql> INSERT INTO items VALUE ( 1, 'Apple', 200, 10 );
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO items VALUE ( 1, 'Orange', 150, 3 );
ERROR 1062 (23000): Duplicate entry '1' for key 'items.id'
mysql> INSERT INTO items VALUE ( 2, 'Pineapple', 1100, 3 );
Query OK, 1 row affected (0.00 sec)
ユニークなカラムはDESC
で表示したテーブル情報のKey
項目にMUL
が表示されます。
また、値の重複ができないため、2回目のレコード追加はエラーが発生しています。
複数カラム
複数カラムの組み合わせにUNIQUE制約を設定できます。
基本構文
CREATE TABLE テーブル名 (
カラム定義1,
カラム定義2,
カラム定義3,
UNIQUE( カラム1, カラム2 )
);
テーブル定義にUNIQUE(カラム1, カラム2)
を記述します。
サンプル
mysql> /* テーブル作成 */
mysql> CREATE TABLE items (
-> id INT,
-> name VARCHAR(20),
-> price INT,
-> stock INT,
-> UNIQUE( id, name )
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> /* テーブル情報 */
mysql> DESC items;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | YES | MUL | NULL | |
| name | varchar(20) | YES | | NULL | |
| price | int | YES | | NULL | |
| stock | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> /* インデックス確認 */
mysql> SHOW INDEX FROM items;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| items | 0 | id | 1 | id | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
| items | 0 | id | 2 | name | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.01 sec)
mysql> /* レコード追加 */
mysql> INSERT INTO items VALUE ( 1, 'Apple', 200, 10 );
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO items VALUE ( 1, 'Orange', 150, 3 );
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO items VALUE ( 2, 'Apple', 250, 10 );
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO items VALUE ( 1, 'Apple', 200, 10 );
ERROR 1062 (23000): Duplicate entry '1-Apple' for key 'items.id'
id
とname
のカラムをユニークに設定しています。
複数カラムの場合、テーブル情報のKey
項目には、最初のカラムのみMUL
が表示されます。
組み合わせの重複できませんが、一方のみのは許可されるので、2、3回目のレコード追加は正常に処理されます。
4回目の追加はid
とname
の組み合わせが重複したためエラーが発生しました。
ユニークカラムの確認
上記で述べたようにDESC
を使ったテーブル情報では、複数カラムのUNIQUE制約の場合、最初のカラムしか分かりません。
正確なユニークカラムを確認するにはSHOW CREATE TABLE
を使って確認できます。
mysql> SHOW CREATE TABLE items;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| items | CREATE TABLE `items` (
`id` int DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`price` int DEFAULT NULL,
`stock` int DEFAULT NULL,
UNIQUE KEY `id` (`id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
注意点
UNIQUE制約のカラムは主キー(PRIMARY KEY)と異なり、NULLが許容されます。
値がNULLの場合、重複していてもエラーを発生せず、レコードが追加されることに注意してください。
mysql> /* テーブル作成 */
mysql> CREATE TABLE items (
-> id INT,
-> name VARCHAR(20),
-> price INT,
-> stock INT,
-> UNIQUE( id, name )
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO items VALUE ( NULL, 'Apple', 200, 10 );
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO items VALUE ( NULL, 'Apple', 200, 10 );
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM items;
+------+-------+-------+-------+
| id | name | price | stock |
+------+-------+-------+-------+
| NULL | Apple | 200 | 10 |
| NULL | Apple | 200 | 10 |
+------+-------+-------+-------+
2 rows in set (0.00 sec)