トップ > SQL入門 > 30章
30章 制約(後半)
では前回に引き続き制約のお話となります。

前回は制約とは?なぜ必要なのか、そして定義方法について学んできました。
今回は制約タイプの続きとなります。

・NOT NULL
・UNIQUE(一意制約)
・PRIMARY KEY(主キー)
・FOREIGN KEY(外部キー)
・CHECK

複合制約


前回は単一列を使用した実行例でしたが、複数列を組合わせて制約を定義することもできます。

  SQL> CREATE TABLE emp3
    2  ( id number(5),
    3    name varchar2(30),
    4    mail varchar2(30),
    5    tel  varchar2(10),
    6    constraint emp2_id_pk primary key(id,name));

  Table created.
  

上記例の場合は、id列とname列に主キー制約を定義しました。
この2つの列の組み合わせで、一意な値のみ挿入できます。

  SQL> INSERT INTO emp3(id,name) VALUES (1,'A');
  
  1 rows created.

  SQL> INSERT INTO emp3(id,name) VALUES (1,'B');
  
  1 rows created.

  SQL> INSERT INTO emp3(id,name) VALUES (1,'A');
  
  INSERT INTO emp3(id,name) VALUES (1,'A');
  *
  ERROR at line 1:
  ORA-00001: unique constraint (ORA.EMP2_ID_PK) violated


上記例では、3つ目のINSERT文が1つ目のINSERT文と
id,name列が同じ値なため、エラーとなっています。

  SQL> INSERT INTO emp3(id,name) values (1,NULL);
  
  INSERT INTO emp3(id,name) values (1,NULL);
  *
  ERROR at line 1:
  ORA-01400: cannot insert NULL into ("ORA"."EMP1"."ID")


上記例ではname列にNULLを挿入しようとしています。
複合索引の主キーでも同様、どちらかの列にNULLを挿入しようとするとエラーとなります。

外部キー制約


では次に外部キー制約について学んでいきましょう。
外部キー制約は少しイメージしづらい制約ですが、ゆっくり理解していきましょう。

外部キー制約は参照する列と同じ値しか挿入できないようにする制約です。
外部キーを定義する場合には参照する表の列名を指定する必要があります。

例えばEMPLOYEES表のDEPT_ID列を参照するDEPARTMENTS表の
DEPT_IDに外部キーを定義したとします。

外部キー制約

上記では最初にINSERTしたDEPT_ID列の値は10です。
10は参照するDEPT_ID列に存在するため、INSERTは成功します。
次の値の20も存在するため、成功します。

次の値の70はDEPT_ID列には存在しない為、エラーとなります。
またNULL値は挿入可能である為、次のINSERT文は成功します。

それでは構文です。

[構文] 列レベル定義 テーブルの作成
 CREATE TABLE 表名 (
 列A データ型 ,
 列B データ型 [ CONSTRAINT 制約名 ]
 REFERENCES 参照する表(列名),
 列C データ型)

[構文] 表レベル定義 テーブルの作成
 CREATE TABLE 表名 (
 列A データ型 ,
 列B データ型 ,
 列C データ型 ,
 [ CONSTRAINT 制約名 ] FOREIGN KEY(列B)
 REFERENCES 参照する表名(列名));

FOREIGN KEYの後ろに指定する列は外部キー制約を定義したい列名を指定します。
REFERENCESの後に指定するのは参照する表名と列名を指定します。

また外部キー制約で使用する参照列は主キー制約か一意制約である必要があります。
そうでない場合は定義するときにエラーが発生します。

今回の例では列レベル、表レベル両方とも列Bに対し、外部キー制約を定義しています。
外部キー制約は以上となります。

CHECK制約


最後にCHECK制約について学んでいきます。

CHECK制約はもっとも柔軟な制約で、自分で挿入する条件を設定することができます。
例えば、挿入する値は整数であるという場合は、

CHECK ( 列名 > 0 )

挿入する値がLから始まるという条件を定義したいのであれば、

CHECK ( 列名 LIKE 'L%' )

WHERE句で使用する条件式を使用して、制約を定義できるのがCHECK制約です。
これはもっとも柔軟ですね。実行例を見ていきましょう。

  SQL> CREATE TABLE emp4
    2  ( id number(5),
    3    name varchar2(30) CONSTRAINT emp3_name_ck
    4    CHECK ( name like 'L%'),
    4    mail varchar2(30) ,
    5    tel  varchar2(10));

  Table created.

  SQL> INSERT INTO emp4(id,name,mail,tel)
    2  VALUES (1,'Lon','AAA','090');

  1 row created.

  SQL> INSERT INTO emp4(id,name,mail,tel)
    2  values (2,'Tom','BBB','080');

  insert into emp4(id,name,mail,tel) values (2,'Tom','BBB','080')
  *
  ERROR at line 1:
  ORA-02290: check constraint (ORA.EMP3_NAME_CK) violated


CHECK制約により大文字Lから始まる値しか挿入できないため、
Tomという値はエラーとなっています。

いかがでしたでしょうか。制約があるおかげで、挿入される値を
毎回チェックしなくてすむようになります。
以上が制約についてのご紹介となります。