SQLで必ず指定する”UNIQUE”という制約ですが、皆さんはこの制約についてきちんと理解していますか?
UNIQUE制約は当たり前のように設定しているけど、何となく漠然とした理解程度でしかないという方もいると思います。
そこで今回の記事ではこの「UNIQUE制約」について、正しい使い方が出来るように解説していきたいと思います。
UNIQUE制約とは
該当カラムにUNIQUE制約に設定すると、設定されたカラムに対しては重複した値を設定することが不可能となります。
これについては、MicrosoftのSQLドキュメントでも次のように記述されています。
SQL Server 2019 (15.x) では、 SQL Server Management Studio または Transact-SQL を使用して UNIQUE 制約を作成し、主キー以外の特定の列に重複した値が入力されないようにします。 UNIQUE 制約を作成すると、対応する一意なインデックスが自動的に作成されます。
主キー(PRIMARY)・一意キー(UNIQUE)とユニークインデックスの違い
混同されがちな項目ですが、一意キー(UNIQUE)はテーブルに付与する制約です。
言い換えると、テーブルに格納されるレコードに対して制限を付けるだけなので、当然「オブジェクト」ではありません。
記述方式に関しても「ALTER TABLE ~」とし、テーブルオブジェクトに対して付与する形となります。
これとは別にもう一つ「主キー(PRIMARY)」というものがありますが、こちらも「一意キー(UNIQUE)」と同じ「制約」となります。
では主キー(PRIMARY)と一意キー(UNIQUE)の違いは?という部分についてですが、以下のような違いがあります。
- 主キー(PRIMARY)は一つのテーブルに対し一つしか作成できません。
- 一意キー(UNIQUE)は一つのテーブルにいくつでも設定することが可能です。
またもう一つ、UNIQUEと似たような名前の「ユニークインデックス」というものがありますが、このユニークインデックスはオブジェクトとなります。
ユニークインデックスを作成するには「CREATE UNIQUE INDEX ~」とします。
一意キー(UNIQUE)とユニークインデックスについてはよく間違った解釈がされてしまうので、しっかりと違いについて把握しておきましょう。
ターミナルでUNIQUEを設定する方法
それではターミナルでUNIQUE制約を設定する方法について解説していきましょう。
まず最初に基本構文の記述についてです。
UNIQUE制約を設定するためには、次のように記述します。
CREATE TABLE テーブル名([[カラム名] UNIQUE], [カラム名], ...);
このように、設定したいカラム名に続けて”半角スペース + UNIQUE”記述するだけの簡単な様式になっています。
念のため、実際のコードで見てみましょう。
まずサンプルとして使用するデータベースとテーブルおよびカラムを作成します。
1> USE smaple_db 2> CREATE TABLE sample_table( 3> no integer UNIQUE, 4> name varchar(MAX), 5> age integer 6> ); 7> SELECT name FROM sysobjects WHERE xtype = 'U' 8> GO name ----------------------------------------------- sample_table 1> SELECT * FROM sample_table 2> GO no name age ----------- ----------- -----------
これで準備は整いました。
それではデータを追加してみます。
1> INSERT INTO sample_table VALUES(1, 'Gordon', 28); 2> INSERT INTO sample_table VALUES(2, 'Smith', 20); 3> INSERT INTO sample_table VALUES(3, 'Williams', 30); 4> GO (1 行処理されました) (1 行処理されました) (1 行処理されました)
単純にデータを追加しただけなので、問題なく追加できました。
それでは今度はUNIQUE指定したカラムに同じ数字を入れてみます。
1> INSERT INTO sample_table VALUES(1, 'Brown', 40); 2> GO メッセージ 2627、レベル 14、状態 1、サーバー DESKTOP-T3J7G2K\SQLEXPRESS、行 1 制約 'UQ__sample_t__3213D0814B10138F' の UNIQUE KEY 違反。オブジェクト 'dbo.sample_table' には重複するキーを挿入できません。重複するキーの値は (1) です。 ステートメントは終了されました。
UNIQUE制約が設定されているため、このようにエラーが返ってくることが確認できます。
なおUNIQUE制約を設定していた場合でも、NULL値は重複して格納できてしまうため、注意しましょう。
組み合わせカラムにUNIQUE制約を適用する方法
ここまではUNIQUEの基本的な使い方としてカラム単体に適用させる方法について解説しましたが、UNIQUEは複数のカラムを組み合わせたものに対しても設定が可能です。
こういったケースでは次のように記述します。
CREATE TABLE テーブル名([カラム名], [カラム名], ..., UNIQUE([カラム名1], [カラム名2], ...));
この記述方法でUNIQUE制約を設定した場合、UNIQUE制約に記述した全てのカラムの値が同じ組み合わせだった場合にのみ重複不可となります。
逆にカラムの値の組み合わせを同一にしなければ、それぞれのカラムの値を重複させてもエラーとはなりません。
それではこちらも実際にコードで確認してみましょう。
1> CREATE TABLE sample_table( 2> no integer, 3> name varchar(30), 4> age integer, 5> UNIQUE(no, name) 6> ); 7> GO 8> SELECT name FROM sysobjects WHERE xtype = 'U' 9> GO name -------------------------------------------------------------------------------------------------------------------------------- sample_table (1 行処理されました) 10> SELECT * FROM sample_table 11> GO no name age ----------- ------------------------------ ----------- 12> INSERT INTO sample_table VALUES(1, 'Gordon', 28); 13> INSERT INTO sample_table VALUES(1, 'Smith', 20); 14> INSERT INTO sample_table VALUES(2, 'Smith', 20); 15> GO (1 行処理されました) (1 行処理されました) (1 行処理されました) 16> INSERT INTO sample_table VALUES(2, 'Smith', 28); 17> GO メッセージ 2627、レベル 14、状態 1、サーバー DESKTOP-T3J7G2K\SQLEXPRESS、行 1 制約 'UQ__sample_t__853DC2704E79437F' の UNIQUE KEY 違反。オブジェクト 'dbo.sample_table' には重複するキーを挿入できません。重複するキーの値は (2, Smith) です。 ステートメントは終了されました。
1行~6行は上の構文に則った記述となっています。
まず見ていただきたいのは、24行~26行の3行です。
今回のケースではUNIQUE制約に「no」と「name」を設定していますが、24行~25行では”no”の値を、25行~26行では”name”の値を敢えて重複させています。
しかしこのINSERT文を実行すると、エラーが返ってくることなく実行されていることが確認できました。
では次は33行目を見てみましょう。
33行目では、既に26行目で登録されている内容の年齢だけを変更してINSERTをかけています。
このINSERTを実行した結果が36行目~となるわけですが、エラーメッセージが返ってきていることが確認できます。
内容を見てみても、37行目に「重複するキーの値は(2, Smith)です。」としっかり記述されています。
このように、UNIQUE制約は記述方法によって異なる動作となりますので、しっかりと違いを把握しておきましょう。
まとめ
いかがでしたか?
今回はUNIQUE制約の記述方法と違いについて解説してみました。
ターミナルから直接設定する機会は比較的少ないと思いますが、こういった方法を知っておけばIDE(統合開発環境)が何らかの理由で使用できない場合でも対応できます。
またSQLはターミナルを使用することで操作が楽になるケースもあるため、学習時には出来るだけターミナルの操作にも慣れておいた方が良いでしょう。
主キー(PRIMARY)や一意キー(UNIQUE)は、作成と同時にユニークインデックスも作成されます。
これは主キー(PRIMARY)や一意キー(UNIQUE)が重複チェックを行う際に、ユニークインデックスを使ってチェックを行っているためです。