ヘッダーをスキップ
Oracle Databaseアドバンスト・アプリケーション開発者ガイド
11gリリース1(11.1)
E05687-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

6 データベース・アプリケーションにおけるデータ整合性のメンテナンス

この章では、制約を使用してデータベースに対応付けたビジネス・ルール(業務規則)を施行する方法、および表に無効な情報が入力されないようにする方法について説明します。

内容は次のとおりです。

制約の概要

制約を使用して表のデータにビジネス・ルールを施行できます。ビジネス・ルールは、常に真または偽になる必要がある条件および関連を指定します。給与、従業員数、在庫調査などに関する方針は会社ごとに異なるため、それぞれのデータベース表に対して異なる規則を指定できます。

整合性制約が表に適用された場合、表のすべてのデータは対応する規則に準拠する必要があります。表のデータを変更するSQL文を発行すると、Oracle Databaseは新しいデータが整合性制約を満たしていることを保証します。プログラムでの確認は行いません。

制約を使用したビジネス・ルールの施行

アプリケーションにロジックを追加するよりも、制約を定義することで、より確実に規則を施行できます。Oracle Databaseでは、表の中のすべてのデータが整合性制約に従っているかどうかをアプリケーションよりも速くチェックできます。

たとえば、各従業員が有効な部門に所属しているかどうかを確認するには、次のようにします。

  1. まず、部門表のすべての値が一意であるという規則を作成します。

    ALTER TABLE dept_tab
      ADD PRIMARY KEY (deptno);
    
  2. 次に、従業員表に示されるすべての部門が、部門表内のいずれかの値と一致するという規則を作成します。

    ALTER TABLE emp_tab
      ADD FOREIGN KEY (deptno)
        REFERENCES dept_tab(deptno);
    

これ以降、表に新しい従業員レコードを追加すると、その部門番号が部門表に存在するかどうかがOracle Databaseによって確認されます。

制約を使用しないでこの規則を施行するには、部門表を問い合せるトリガーを使用して、新しい従業員の部門が有効かどうかをテストします。Oracle DatabaseのSELECT文では読取り一貫性(CR)が使用されるため、この方法は制約を使用するよりも信頼性が低いため、この問合せは、他のトランザクションからのコミットされていない変更を見落とす場合があります。

アプリケーション・ロジックを使用したビジネス・ルールの施行

挿入または更新を行う前に不正なデータをフィルタ除去できる場合は、アプリケーション・ロジックおよび制約を介してビジネス・ルールを施行できます。これによって、ユーザーにすぐにフィードバックでき、データベースの負荷を削減できます。この方法は、表内のデータを確認しなくても、データの値が不正または範囲外であると判断できる場合に適しています。

制約で使用する索引の作成

使用可能なすべての一意キーおよび主キーには、対応する索引が必要です。これらの索引は、データベースに自動的に作成させるのではなく、手動で作成します。次のことに注意してください。

  • 新しい索引を作成するのではなく、できるだけ既存の索引を使用するようにします。

  • 一意キーおよび主キーは、一意索引と同様に非一意索引を使用できます。非一意索引の最初の数列のみでも使用できます。

  • 多くても1つの一意キーまたは主キーが、それぞれの非一意索引を使用できます。

  • 索引の列順序と制約は一致する必要がありません。

  • 索引を削除する場合など、制約が索引を使用しているかどうかを確認する必要がある場合、一意キー制約または主キー制約が使用している索引のオブジェクト番号は、その制約のCDEF$.ENABLEDに格納されています。これは、静的データ・ディクショナリ・ビューまたは動的なパフォーマンス・ビューには表示されません。

  • Oracle Databaseでは、自動的に外部キーに索引を付けることはありません。

NOT NULL制約を使用する場合

デフォルトでは、すべての列がNULL値を含むことができます。NOT NULL制約は、常に値が必要とされる列のみに定義します。たとえば、一時的に新しい従業員のマネージャまたは入社日に値が入っていなくても、特に問題はありません。また、従業員の中には、コミッション(歩合)を受けていない人もいます。これらの列は、NOT NULL制約の対象にできません。ただし、従業員の名前は最初から必要であるため、NOT NULL整合性制約を使用してこの規則を施行できます。

NOT NULL制約を他の制約と組み合せて、特定の列に存在できる値をさらに制限することがよくあります。たとえば、NOT NULLと一意キー制約を組み合せると、一意キーに必ず値が入力され、新しい行のデータと既存の行のデータが競合する可能性がなくなります。

Oracle Database索引は、すべてがNULLのキーは格納しません。したがって、表の索引のみをスキャンする場合、またはすべての行に索引付けが必要な操作を実行する場合は、1つ以上の索引列にNOT NULL制約を付けます。

NOT NULL制約は次のように指定します。

ALTER TABLE table_name MODIFY column_name NOT NULL;

例6-1に、EMPLOYEES表のどの列にNOT NULL制約があるか、NOT NULL制約がある列にNULL値を挿入しようとするとどうなるかを示します。

例6-1 NOT NULL制約がある列へのNULL値の挿入

SQL> CONNECT HR
Enter password: password
Connected.
SQL>
SQL> DESCRIBE EMPLOYEES;
Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 EMPLOYEE_ID                               NOT NULL NUMBER(6)
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)
 EMAIL                                     NOT NULL VARCHAR2(25)
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE
 JOB_ID                                    NOT NULL VARCHAR2(10)
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)

SQL>
SQL> INSERT INTO EMPLOYEES
  2    VALUES (NULL, 'John', 'Doe', 'johndoe@example.com',
  3            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  VALUES (NULL, 'John', 'Doe', 'johndoe@example.com',
          *
ERROR at line 2:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMPLOYEE_ID")

SQL>
SQL> INSERT INTO EMPLOYEES
  2    VALUES (123456, 'John', 'Doe', 'johndoe@example.com',
  3            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
          NULL, NULL, NULL, NULL, NULL, NULL, NULL)
                *
ERROR at line 3:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."HIRE_DATE")

SQL>

デフォルトの列値を使用する場合

デフォルト値は、代表的な値を含む列に割り当てます。たとえば、DEPT_TAB表において、ほとんどの部門がニューヨークにある場合、NEW YORKLOC列のデフォルト値に設定できます。

エントリを持たない列に0(ゼロ)などのデフォルト値が適用される場合、エラーの回避に有効です。たとえば、デフォルト値を0(ゼロ)に設定すると、次のテストは、

IF sal IS NOT NULL AND sal < 50000

次のように、より簡単な書式に変更できます。

IF sal < 50000

ビジネス・ルールに応じて、デフォルト値を0(ゼロ)または偽に設定できます。また、デフォルト値をNULLのままにして、不明な値を示すこともできます。

また、表の一部の列を参照可能にするためのビューを作成する場合も、デフォルトは有効です。たとえば、ビューを介してユーザーが行を挿入できるようにしていることがあります。実表には、ビューの定義には含まれていない列で、各行を挿入するユーザーを記録するinserter列がある場合もあります。ユーザー名を自動的に記録するには、USER関数を起動するデフォルト値を定義します。

CREATE TABLE audit_trail (
  value1   NUMBER,
  value2   VARCHAR2(32),
  inserter VARCHAR2(30) DEFAULT USER);

デフォルトの列値の設定

デフォルト値は、任意のリテラルまたはほとんどの式を使用して定義できます。これには、次のコールも含まれます。

  • SYSDATE

  • SYS_CONTEXT

  • USER

  • USERENV

  • UID

デフォルト値には、順序、PL/SQLファンクション、列、LEVELROWNUMまたはPRIORを参照する式を含めることはできません。デフォルトのリテラルまたは式のデータ型は、その列のデータ型と一致しているか、または変換できる必要があります。

デフォルト値が、SQL関数の結果の場合もあります。たとえば、SYS_CONTEXTをコールすると、ユーザー名などの条件に応じて異なるデフォルト値が設定されます。デフォルト値として使用するには、SQL関数のパラメータがすべてリテラルで、他の列の参照および他の関数の起動ができない必要があります。

デフォルト値が列に対して明示的に定義されない場合、その列のデフォルトは暗黙的にNULLに設定されます。

INSERT文内で、リテラル値のかわりにDEFAULTキーワードを使用できます。これによって、対応するデフォルト値が挿入されます。

表の主キーの選択

表ごとに、1つの主キーを含めることができます。主キーを使用すると、表の各行を一意に識別でき、また、行の重複も回避できます。主キーを選択するときには、次のガイドラインを使用してください。

  • 順序番号を含む列を使用します。これは、他のすべてのガイドラインを満たします。

  • データ値が一意である列を選択します。これは、主キーの目的が表の各行を一意に識別することであるためです。

  • データ値が変更されない列を選択します。主キー値は、表の行を識別するためにのみ使用されます。主キーには、他の目的のために使用されるデータを含めることはできません。

  • NULLを含まない列を選択します。主キー制約では、定義によって主キーを構成する列にNULLが含まれている行は許可されません。

  • 短い数値型の列を選択します。短い主キーは入力が簡単です。数値の主キーは、順序番号を使用して簡単に生成できます。

  • 複合主キーの使用は最小限に抑えます。複合主キーは、使用できますが、他のすべての推奨項目を満たすわけではありません。たとえば、複合主キー値は、順序番号で割り当てることができません。

一意制約を使用する場合

一意キーに指定する列は、慎重に選択してください。この制約の目的は、主キーの目的とは異なります。一意キー制約は、値の重複が許されない列に適しています。主キーは表の各行を一意に識別し、通常、一意であること以外は重要ではない値を含みます。図6-1に、一意キー制約を使用した表の例を示します。

図6-1 一意制約を使用した表

一意制約を使用した表
「図6-1 一意制約を使用した表」の説明


注意:

複合一意キー制約のある非NULL列内には同一の値を入力できません(一意キー制約ではNULL値を入力できます)。

適切な一意キーの使用例は次のとおりです。

  • 従業員の社会保障番号(主キーは従業員番号)

  • トラックのナンバー・プレートの番号(主キーはトラック番号)

  • AREA_CODELOCAL_PHONEの2列からなる顧客電話番号(主キーは顧客番号)

  • 部門名と所在地(主キーは部門番号)

ビューに対して制約を使用する場合

この章で説明している制約は、ビューではなく表に適用されるものです。

ビューにも制約を宣言できますが、その制約はデータの整合性を保持するには有効ではありません。これらの制約は、ビューを伴う問合せをリライトするために使用されます。これによって、マテリアライズド・ビューおよびその他のデータ・ウェアハウス機能を使用した場合のパフォーマンスが向上します。これらの制約は、常にDISABLEキーワードを使用して宣言されます。VALIDATEキーワードは使用できません。この場合、制約は施行されず、対応付けられた索引はありません。


関連項目:

データ・ウェアハウスでの制約の使用の詳細は、『Oracle Databaseデータ・ウェアハウス・ガイド』を参照してください。

制約を使用した参照整合性の施行

2つの表に1つ以上の共通の列が含まれる場合、Oracle Databaseでは、参照整合性制約を使用して2つの表に関連を規定できます。親表(完全な列値の集合を持つ表)の列に、キー制約または一意キー制約を定義します。子表の列(他の表の値を参照する値を含む表)には、外部キー制約を定義します。


関連項目:

外部キーを含むその他の制約の定義の詳細は、「親表と子表との関連の定義」を参照してください。

図6-2に、部門番号に定義された外部キーを示します。この外部キーは、この列の値がそれぞれ部門表の主キーの値と一致することを保証します。制約によって、間違った部門番号が従業員表に入力される可能性を回避できます。

外部キーは、複数の列で構成することもできます。このような複合外部キーは、正確に同じ構造(列の数とデータ型が同一)を持つ複合主キーまたは複合一意キーを参照する必要があります。複合主キーまたは複合一意キーには32列までという制限があるため、複合外部キーも最大32列に制限されます。

図6-2 外部キー制約を使用した表

外部キー制約を使用した表
「図6-2 外部キー制約を使用した表」の説明

外部キー制約およびNULL値

外部キーには、一致する主キーまたは一意キーがない場合でも、すべてNULLのキー値を使用できます。

  • デフォルトでは(NOT NULL句またはCHECK句を指定しない場合)、外部キー制約は、ANSI/ISO規格の複合外部キーに対して不一致規則を施行します。

  • 複合外部キーのNULL値に対する完全一致規則(キーのすべての構成要素がNULLであるか、NULL以外のものであることを要求する)を施行するには、すべての複合外部キーがNULLまたは非NULLであることのみを許可するCHECK制約を定義します。たとえば、列ABCで構成される複合キーを次のとおり指定できます。

    CHECK ((A IS NULL AND B IS NULL AND C IS NULL) OR
           (A IS NOT NULL AND B IS NOT NULL AND C IS NOT NULL))
    
  • 一般に、宣言型参照整合性を基にして、複合外部キーのNULL値に対する部分一致規則(NULL以外の列が、参照先の主キーまたは一意キー列の同等の位置にあること)を施行することはできません。この場合、『Oracle Database PL/SQL言語リファレンス』で説明するように、トリガーを使用して処理できることがよくあります。

親表と子表との関連の定義

親表と子表との関連のいくつかは、子表の外部キーで定義されている他のタイプの制約によって判断できます。

外部キーに他の制約がない場合 外部キーについて他の制約が定義されていない場合は、子表の行は何行でも同一の親キー値を参照できます。このモデルでは、外部キーにNULLが許可されます。

このモデルは、外部キーに未定の値(NULL)を許可する親キーと外部キーとの間に1対多関連を確立します。従業員表と部門表の間のこのような関連の例を、図6-2に示します。各部門(親キー)には多数の従業員(外部キー)が所属しますが、一部の従業員は、部門に所属していない場合があります(外部キーでNULL)。

外部キーにNOT NULL制約がある場合 外部キーでNULLが許可されていない場合は、子表の各行は親キーの値を明示的に参照する必要があります。

子表の行は何行でも同一の親キー値を参照できるため、このモデルは、親キーと外部キーとの1対1関連を確立します。ただし、子表の各行は、必ず親キー値に対する参照を持っている必要があり、外部キーに値の欠如(NULL)があってはいけません。前述の項の例を使用して、この関連を説明できます。ただし、このモデルでは、従業員は必ず特定の部門への参照を持つ必要があります。

外部キーに一意キー制約がある場合 外部キーに一意キー制約が定義されている場合は、子表の中の1行のみが、親キー値を参照できます。このモデルでは、外部キーにNULLが許可されます。

このモデルは、外部キーに未定の値(NULL)を許可する親キーと外部キーとの間に1対1関連を確立します。たとえば、従業員表に、企業の保険計画の従業員の会員番号を参照するMEMBERNOという名前の列があると想定します。また、INSURANCEという表には、MEMBERNOという主キーがあり、その他の列は保険証書に関連した各従業員の情報を保持しているとします。次の理由によって、従業員表のMEMBERNOは、外部キーかつ一意キーである必要があります。

  • EMP_TAB表およびINSURANCE表の参照整合性規則を施行するため(外部キー制約)

  • 各従業員の会員番号を一意にするため(一意キー制約)

外部キーに一意キー制約およびNOT NULL制約がある場合 一意キー制約およびNOT NULL制約の両方が外部キーに定義されている場合は、子表の1行のみが指定された親キー値を参照できます。外部キーではNULL値を使用できないため、子表の各行は、親キーの値を明示的に参照する必要があります。

このモデルは、外部キーに未定の値(NULL)を許可しない親キーと外部キーとの間に1対1関連を確立します。前述の例を拡張して、各従業員が一意の会員番号を持つように保証するとともに、従業員表のMEMBERNO列にNOT NULL制約を追加することで、従業員表のMEMBERNO列に未定義の値(NULL)が許可されないようにできます。

複数の外部キー制約に関する規則

Oracle Databaseでは、1つの列を複数の外部キー制約で参照できます。依存キーの数に制限はありません。ある列が2つの異なる複合外部キーの一部になっている場合に、この状況が発生する可能性があります。

制約チェックの遅延

Oracle Databaseが制約を確認する場合に、制約が満たされないときは、エラーが表示されます。現行のトランザクションが終了するまで制約のチェックを遅延するには、SET CONSTRAINTS文を使用します。


注意:

SET CONSTRAINTS文は、トリガー内では使用できません。

制約のチェックを遅延するには次のようにします。

  • データを適切に選択します。

    データに次のいずれかの特性がある場合、一意キーおよび外部キーの制約チェックを遅延する必要があります。

    • 表がスナップショットの場合

    • 別のアプリケーションで処理される大量のデータを含む表であり、同じ順序でデータが戻されるかどうかわからない場合

  • 外部キーに対するカスケード操作を更新します。

  • 制約が遅延可能かどうかを確認します。

    適切な表を指定した後、表の外部キー、一意キーおよび主キーがDEFERRABLEとして作成されているかどうかを確認します。

  • データを処理するアプリケーション内で、任意のデータを処理する前に、次のようにすべての制約に遅延を設定します。

    SET CONSTRAINTS ALL DEFERRED;
    
  • (オプション)トランザクションをコミットする直前に制約違反をチェックします。

    COMMIT文の直前に、SET CONSTRAINTS ALL IMMEDIATE文を実行します。制約に問題があった場合、この文は失敗し、エラーの原因になった制約が識別されます。制約が違反しているときにコミットした場合、トランザクションはロールバックされ、エラー・メッセージが表示されます。

例6-2では、表empの主キーと外部キーがDEFERRABLEとして作成され、遅延されます。

例6-2 制約チェックの遅延

SQL> -- Create dept table:
SQL>
SQL> DROP TABLE dept;
DROP TABLE dept
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE dept (
  2    deptno NUMBER PRIMARY KEY,
  3    dname  VARCHAR2 (30)
  4  );

Table created.

SQL>
SQL> -- Create emp table with deferrable primary & foreign constraints:
SQL>
SQL> DROP TABLE emp;
DROP TABLE emp
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE emp (
  2    empno  NUMBER,
  3    ename  VARCHAR2(30),
  4    deptno NUMBER,
  5    CONSTRAINT pk_emp_empno PRIMARY KEY (empno) DEFERRABLE,
  6    CONSTRAINT fk_emp_deptno FOREIGN KEY (deptno) REFERENCES dept(deptno) DEFERRABLE
  7  );

Table created.

SQL>
SQL> -- Populate tables:
SQL>
SQL> INSERT INTO dept VALUES (10, 'Accounting');

1 row created.

SQL> INSERT INTO dept VALUES (20, 'SALES');

1 row created.

SQL> INSERT INTO emp VALUES (1, 'Corleone', 10);

1 row created.

SQL> INSERT INTO emp VALUES (2, 'Costanza', 20);

1 row created.

SQL> COMMIT;

Commit complete.

SQL>
SQL> -- Defer constraint checking & update tables:
SQL>
SQL> SET CONSTRAINTS ALL DEFERRED;

Constraint set.

SQL>
SQL> UPDATE dept
  2    SET deptno = deptno + 10
  3      WHERE deptno = 20;

1 row updated.

SQL>
SQL> SELECT * from dept
  2    ORDER BY deptno;

    DEPTNO DNAME
---------- ------------------------------
        10 Accounting
        30 SALES

2 rows selected.

SQL>
SQL> UPDATE emp
  2    SET deptno = deptno + 10
  3      WHERE deptno = 20;

1 row updated.

SQL>
SQL> SELECT * from emp
  2    ORDER BY deptno;

     EMPNO ENAME                              DEPTNO
---------- ------------------------------ ----------
         1 Corleone                               10
         2 Costanza                               30

2 rows selected.

SQL>

SET CONSTRAINTSは現行のトランザクションのみに適用されます。設定が継続するのは、そのトランザクションの間、または次のSET CONSTRAINTS文によってモードがリセットされるまでです。ALTER SESSION SET CONSTRAINTS文は、現行セッションにのみ適用されます。制約の作成時に指定したデフォルト値は、制約が存在するかぎり維持されます。


関連項目:

SET CONSTRAINTS文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

制約に対応付けられた索引の領域と時間のオーバーヘッドの最小化

一意キーまたは主キーを作成すると、Oracle Databaseは、制約の一意性を強制するために既存の索引が使用できるかどうかを確認します。既存の索引がない場合、データベースは索引を作成します。

Oracle Databaseが一意索引を使用して制約を施行し、それに対応付けられた制約が削除または使用禁止にされる場合、索引は削除されます。索引に関連付けられた統計を保持する場合(再作成には時間がかかる)は、制約のDROP文にKEEP INDEX句を指定します。

使用可能な外部キーが主キーまたは一意キーを参照している間は、主キー制約または一意キー制約、または索引を使用禁止にしたり削除することはできません。


注意:

遅延可能制約を使用した一意キーおよび主キーには、非一意索引を使用してください。

一意キー制約および主キー制約の作成時に既存の索引を使用するには、CONSTRAINT句にUSING INDEXを含めます。詳細と例は、『Oracle Database SQL言語リファレンス』を参照してください。

外部キーを索引付けするためのガイドライン

一致する一意キーまたは主キーが決して更新または削除されない場合にかぎり、外部キーに索引を付けます。


関連項目:

外部キーの索引付けの詳細は、『Oracle Database概要』を参照してください。

分散データベース内の参照整合性

参照制約の宣言では、リモート表の主キーまたは一意キーを参照する外部キーを指定できません。

ただし、トリガーを使用すると、複数のノードにまたがる親子の表の関連をメンテナンスできます。


関連項目:

参照整合性を施行するトリガーの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。


注意:

トリガーを使用して分散データベースの複数のノードにまたがる参照整合性を定義する場合、ネットワーク障害が親表および子表へのアクセスを制限する可能性があることに注意してください。

たとえば、子表がSALESデータベースに存在し、親表がHQデータベースに存在すると想定します。

2つのデータベース間のネットワーク接続に障害が発生すると、参照整合性トリガーがHQデータベース内の親表へアクセスする必要があるため、子表に対するDML文が処理(行を挿入したり、外部キーの値を更新するような処理)を進めることができない場合があります。


CHECK制約を使用する場合

比較などの論理式をベースとした整合性規則を施行する必要がある場合、CHECK制約を使用します。その他のタイプの制約で必要なチェックができる場合には、CHECK制約は使用しないでください。

CHECK制約の例を次に示します。

CHECK制約の制限

CHECK制約では、条件は表のすべての行に対して真または不明である必要があります。条件が偽であると評価された場合、その文はロールバックされます。CHECK制約の条件には、次のような制限があります。

  • 条件は、挿入または更新が行われている行の値を使用して評価できるブール式である必要があります。

  • 条件に副問合せまたは順序を含めることはできません。

  • 条件にSQL関数SYSDATEUIDUSERまたはUSERENVを含めることはできません。

  • 条件に疑似列LEVELまたはROWNUMを含めることはできません。

  • 条件にPRIOR演算子を含めることはできません。

  • 条件にユーザー定義関数を含めることはできません。


関連項目:

  • LEVEL疑似列の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

  • ROWNUM疑似列の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

  • PRIOR演算子(階層問合せで使用)の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。


CHECK制約の設計

CHECK制約は、条件が偽であると評価される場合にのみCHECK制約に違反します。真および不明(NULLと比較して)はチェック条件には違反しません。したがって、定義するCHECK制約が、規則を施行するために十分明確であることを確認してください。

たとえば、次のCHECK制約について考えます。

CHECK (Sal > 0 OR Comm >= 0)

この規則は、「従業員の給与が0(ゼロ)より大きい場合、または従業員のコミッションが0(ゼロ)以上の場合は、従業員表の行を許可しない」と解釈されます。ただし、給与にNULLの値を持つ行は、チェック条件全体が不明であると評価されるため、そのコミッションの値の評価にかかわらず、CHECK制約に違反しません。このような場合には、SAL列とCOMM列の両方にNOT NULL制約を設定することによって、このような違反を回避できます。


注意:

どのような場合にNULL条件の結果が不明な値となるかについては、『Oracle Database SQL言語リファレンス』の論理演算子の真理値表を参照してください。

複数のCHECK制約に関する規則

1つの列に、その定義で列を参照する複数のCHECK制約を指定できます。定義できるCHECK制約の数に制限はありません。

制約が評価される順序は定義されません。そのため、順序に依存したり、互いに競合するような複数の制約を定義しないでください。

CHECKおよびNOT NULL制約の選択

ANSI/ISO規格によると、NOT NULL制約はCHECK制約の1つであり、その条件は次のとおりです。

CHECK (column_name IS NOT NULL)

このため、NOT NULL制約またはCHECK制約のいずれかを使用して、単一列に対するNOT NULL制約を記述できます。NOT NULL制約は、CHECK制約よりも簡単に使用できます。

複合キーがすべてNULLまたはすべて値を持つ場合は、CHECK制約を使用する必要があります。たとえば、次のCHECK制約を指定すると、列C1およびC2を構成する複合キーのキー値が、すべてNULLまたはすべて値を持つことができます。

CHECK ((C1 IS NULL AND C2 IS NULL) OR (C1 IS NOT NULL AND C2 IS NOT NULL))

制約の定義の例

例6-3および例6-4に、データベース設計のプロトタイプ・フェーズでの簡単な制約の作成方法を示します。これらの例では各制約に名前が付いています。制約に名前を付けると、DDLが複数回実行された場合に、システムが生成した異なる名前で、データベースが同じ制約の複数のコピーを作成することを回避できます。

例6-3では、CREATE TABLE文を使用して表と制約を同時に作成します。

例6-3: CREATE TABLE文を使用した制約の定義

SQL> DROP TABLE DeptTab;
Table dropped.

SQL>
SQL> CREATE TABLE DeptTab (
  2    Deptno  NUMBER(3) CONSTRAINT pk_DeptTab_Deptno PRIMARY KEY,
  3    Dname   VARCHAR2(15),
  4    Loc     VARCHAR2(15),
  5    CONSTRAINT u_DeptTab_Dname_Loc UNIQUE (Dname, Loc),
  6    CONSTRAINT c_DeptTab_Loc
  7      CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')));

Table created.

SQL>
SQL> DROP TABLE EmpTab;
DROP TABLE EmpTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE EmpTab (
  2    Empno    NUMBER(5) CONSTRAINT pk_EmpTab_Empno PRIMARY KEY,
  3    Ename    VARCHAR2(15) NOT NULL,
  4    Job      VARCHAR2(10),
  5    Mgr      NUMBER(5) CONSTRAINT r_EmpTab_Mgr REFERENCES EmpTab,
  6    Hiredate DATE,
  7    Sal      NUMBER(7,2),
  8    Comm     NUMBER(5,2),
  9    Deptno   NUMBER(3) NOT NULL
 10    CONSTRAINT r_EmpTab_DeptTab REFERENCES DeptTab ON DELETE CASCADE);

Table created.

SQL>

例6-4では、ALTER TABLE文を使用して既存の表に制約を作成します。

制約に違反する行が表にすでに存在している場合、VALIDATED状態の制約は作成できません。

例6-4: ALTER TABLE文を使用した制約の定義

SQL> -- Create tables without constraints:
SQL>
SQL> DROP TABLE DeptTab;

Table dropped.

SQL>
SQL> CREATE TABLE DeptTab (
  2    Deptno  NUMBER(3),
  3    Dname   VARCHAR2(15),
  4    Loc     VARCHAR2(15)
  5  );

Table created.

SQL>
SQL> DROP TABLE EmpTab;
DROP TABLE EmpTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL>
SQL> CREATE TABLE EmpTab (
  2    Empno    NUMBER(5),
  3    Ename    VARCHAR2(15),
  4    Job      VARCHAR2(10),
  5    Mgr      NUMBER(5),
  6    Hiredate DATE,
  7    Sal      NUMBER(7,2),
  8    Comm     NUMBER(5,2),
  9    Deptno   NUMBER(3)
 10  );

Table created.

SQL>
SQL> --Define constraints with the ALTER TABLE statement:
SQL>
SQL> ALTER TABLE DeptTab
  2    ADD CONSTRAINT pk_DeptTab_Deptno PRIMARY KEY (Deptno);

Table altered.

SQL>
SQL> ALTER TABLE EmpTab
  2    ADD CONSTRAINT fk_DeptTab_Deptno
  3      FOREIGN KEY (Deptno) REFERENCES DeptTab;

Table altered.

SQL>
SQL> ALTER TABLE EmpTab MODIFY (Ename VARCHAR2(15) NOT NULL);

Table altered.

SQL>

関連項目:

大規模な本番データベースに対する制約の作成方法およびメンテナンス方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

制約の定義に必要な権限

制約を作成するには、制約のある表を作成する権限(CREATE TABLEまたはCREATE ANY TABLEシステム権限)または変更する権限(表に対するALTERオブジェクト権限またはALTER ANY TABLEシステム権限)が必要です。さらに、一意キーおよび主キー制約では、表の所有者に、対応する索引を含む表領域の割当て制限またはUNLIMITED TABLESPACEシステム権限のいずれかが必要です。外部キー制約では、その他にもいくつかの権限が必要です。

制約のネーミング

NOT NULL一意キー、主キー、外部キーおよびCHECKの各制約に対して、制約句のCONSTRAINTオプションを使用して名前を割り当ててください。この名前は、そのユーザーが所有している他の制約名に対して一意である必要があります。制約名を指定しない場合、Oracle Databaseが名前を自動的に生成して割り当てます。

独自の名前を指定すると、制約違反のエラー・メッセージがよりわかりやすくなります。また、SQL文が複数回実行された場合に、異なる名前で重複した制約が作成されることを回避できます。

制約句のCONSTRAINTオプションの例として、前述のCREATE TABLE文およびALTER TABLE文の例を参照してください。なお、データ・ディクショナリでは、制約名の他に、その制約に関する他の情報も参照できます。


関連項目:

静的データ・ディクショナリ・ビューの例は、「制約に関する情報の表示」を参照してください。

制約の使用可能および使用禁止

この項では、制約をユーザー自身で使用可能および使用禁止にするしくみ、および手順について説明します。

使用可能にされた制約。制約が使用可能な場合、対応する規則が対応付けられた列のデータ値に施行されます。制約の定義は、データ・ディクショナリ内に格納されます。

使用禁止にされた制約。制約が使用禁止の場合、それに対応する規則は施行されません。制約の定義は、データ・ディクショナリ内に格納されたままです。

整合性制約は、データベース内のデータに関するアサーションを表します。このアサーションは、制約を使用可能にすると必ず真になります。制約を使用禁止にすると、整合性制約に違反するデータがデータベース内に存在する可能性があるため、アサーションは真である場合も真でない場合もあります。

内容は次のとおりです。

制約を使用禁止にする理由

日常の操作では、制約を使用可能な状態にしておきます。特定の状況においては、パフォーマンス上の理由から、表の制約を一時的に使用禁止にする必要がある場合があります。次に例を示します。

  • SQL*Loaderを使用して、表に大量のデータをロードする場合

  • 表に対して大規模な変更を行うバッチ作業を実施する場合(たとえば、既存の番号に1000を加えてすべての従業員番号を変更する場合)

  • 表を1つずつインポートまたはエクスポートする場合

制約を一時的に使用禁止にすると、これらの操作が高速になります。

制約を使用可能にする(デフォルト)

整合性制約を定義すると(CREATE TABLEまたはALTER TABLEを使用)、Oracle Databaseではデフォルトで制約が使用可能になります。コードをわかりやすくするために、例6-5のように、制約の定義にENABLE句を含めて制約を明示的に使用可能にできます。

例6-5 制約を使用可能にする

SQL> /* Use CREATE TABLE statement to create enabled constraint
SQL>    (ENABLE keyword is optional): */
SQL>
SQL> DROP TABLE t1;
DROP TABLE t1
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE t1
  2    (Empno NUMBER(5) PRIMARY KEY ENABLE);

Table created.

SQL>
SQL> /* Create table without constraint
SQL>    & then use ALTER TABLE statement to add enabled constraint
SQL>    (ENABLE keyword is optional): */
SQL>
SQL> DROP TABLE t2;
DROP TABLE t2
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE t2 (
  2    Empno NUMBER(5));

Table created.

SQL>
SQL> ALTER TABLE t2
  2    ADD PRIMARY KEY (Empno) ENABLE;

Table altered.

SQL>

個々のトランザクションによって一度に1つずつ行が移入される表の制約を定義する場合は、ENABLE句を指定します。こうすることで、データが常に一貫性を保つことが保証され、各DML操作のパフォーマンス・オーバーヘッドが少なくなります。

整合性制約を使用可能にするALTER TABLE文は、表の既存の行がその整合性制約に違反するとエラーになります。文はロールバックされ、制約定義は格納されず使用可能にもなりません。


関連項目:

制約に違反する行の詳細は、「制約の例外の修正」を参照してください。

制約を使用禁止にする

整合性制約を定義(CREATE TABLEまたはALTER TABLEを使用)して使用禁止にするには、例6-6のように定義にDISABLE句を指定します。

例6-6 制約を使用禁止にする

SQL> /* Use CREATE TABLE statement to create disabled constraint */
SQL>
SQL> DROP TABLE t1;
DROP TABLE t1
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE t1
  2    (Empno NUMBER(5) PRIMARY KEY DISABLE);

Table created.

SQL>
SQL> /* Create table without constraint
SQL>    & then use ALTER TABLE statement to add disabled constraint */
SQL>
SQL> DROP TABLE t2;
DROP TABLE t2
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE t2 (
  2    Empno NUMBER(5));

Table created.

SQL>
SQL> ALTER TABLE t2
  2    ADD PRIMARY KEY (Empno) DISABLE;

Table altered.

SQL>

ユーザーがアクセスする前に大容量のデータが挿入される表の制約を定義するときは、DISABLE句を指定します。特に、データの挿入後にデータをクリーン・アップしたり、空の列に順序番号または親子関係を入力する必要がある場合です。

制約を定義して使用禁止にするALTER TABLE文は、その規則が施行されていないため、エラーとなることはありません。

既存の制約を使用可能にする

データをクリーン・アップし、空の列に値を入力した後で、データの挿入中に使用禁止にしていた制約を使用可能にできます。

既存の制約を使用可能にするには、例6-7のようにALTER TABLE文をENABLE句とともに使用します。

例6-7 既存の制約を使用可能にする

SQL> -- Create table with disabled constraints:
SQL>
SQL> DROP TABLE DeptTab;
DROP TABLE DeptTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE DeptTab (
  2     Deptno  NUMBER(3) PRIMARY KEY DISABLE,
  3     Dname   VARCHAR2(15),
  4     Loc     VARCHAR2(15),
  5     CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc) DISABLE,
  6     CONSTRAINT c_DeptTab_Loc
  7       CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) DISABLE
  8  );

Table created.

SQL>
SQL> -- Enable constraints:
SQL>
SQL> ALTER TABLE DeptTab
  2    ENABLE PRIMARY KEY
  3    ENABLE CONSTRAINT uk_DeptTab_Dname_Loc
  4    ENABLE CONSTRAINT c_DeptTab_Loc;

Table altered.

SQL>

整合性制約を使用可能にするALTER TABLE文は、表の行がその整合性制約に違反するとエラーになります。この場合、文はロールバックされ、制約は使用可能になりません。


関連項目:

制約に違反する行の詳細は、「制約の例外の修正」を参照してください。

既存の制約を使用禁止にする

すでにデータが含まれている表に対して、大規模な挿入または更新を実行する必要がある場合は、整合性制約を一時的に使用禁止にして、バルク操作のパフォーマンスを向上させることができます。

既存の制約を使用禁止にするには、例6-8のようにALTER TABLE文をDISABLE句とともに使用します。

例6-8 既存の制約を使用禁止にする

SQL> -- Create table with enabled constraints:
SQL>
SQL> DROP TABLE DeptTab;
DROP TABLE DeptTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE DeptTab (
  2     Deptno  NUMBER(3) PRIMARY KEY ENABLE,
  3     Dname   VARCHAR2(15),
  4     Loc     VARCHAR2(15),
  5     CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc) ENABLE,
  6     CONSTRAINT c_DeptTab_Loc
  7       CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) ENABLE
  8  );

Table created.

SQL>
SQL> -- Disable constraints:
SQL>
SQL> ALTER TABLE DeptTab
  2    DISABLE PRIMARY KEY
  3    DISABLE CONSTRAINT uk_DeptTab_Dname_Loc
  4    DISABLE CONSTRAINT c_DeptTab_Loc;

Table altered.

SQL>

キー制約の使用可能および使用禁止に関するガイドライン

一意キー、主キーおよび外部キーの各制約を使用可能または使用禁止にする場合は、いくつかの重要な問題および前提条件を認識してください。一意キー制約および主キー制約は、通常、データベース管理者が管理します。


関連項目:

『Oracle Database管理者ガイド』および「外部キー制約の管理」

制約の例外の修正

表の行が整合性制約に違反する場合、この行は制約違反になり、制約に対する例外とされます。例外が存在する場合、制約を使用可能にはできません。制約に違反する行は、制約を使用可能にする前に更新または削除する必要があります。

制約を使用可能にするときに、特定の整合性制約に対する例外を指定できます。


関連項目:

この手順の詳細は、「制約の例外の修正」を参照してください。

制約を作成または使用可能にするときに、整合性制約の例外があるために文が正常に実行されなかった場合、文はロールバックされます。この場合、すべての例外が更新または削除されるまで制約を使用可能にできません。整合性制約に違反している行を判断するには、CREATE TABLE文またはALTER TABLE文のENABLE句にEXCEPTIONSオプションを指定します。


関連項目:

制約の例外に応答する場合は、『Oracle Database管理者ガイド』を参照してください。

制約の変更

Oracle8i以降では、例6-9のようにMODIFY CONSTRAINT句を使用して既存の制約状態を変更することができます。


関連項目:

変更するパラメータの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

例6-9 制約の変更

SQL> /* Create & then modify a CHECK constraint: */
SQL>
SQL> DROP TABLE X1Tab;
DROP TABLE X1Tab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE X1Tab (
  2    a1 NUMBER
  3      CONSTRAINT c_X1Tab_a1 CHECK (a1>3)
  4        DEFERRABLE DISABLE
  5  );

Table created.

SQL>
SQL> ALTER TABLE X1Tab
  2    MODIFY CONSTRAINT c_X1Tab_a1 ENABLE;

Table altered.

SQL>
SQL> ALTER TABLE X1Tab
  2    MODIFY CONSTRAINT c_X1Tab_a1 RELY;

Table altered.

SQL>
SQL> ALTER TABLE X1Tab
  2    MODIFY CONSTRAINT c_X1Tab_a1 INITIALLY DEFERRED;

Table altered.

SQL>
SQL> ALTER TABLE X1Tab
  2    MODIFY CONSTRAINT c_X1Tab_a1 ENABLE NOVALIDATE;

Table altered.

SQL>
SQL> /* Create & then modify a PRIMARY KEY constraint: */
SQL>
SQL> DROP TABLE t1;
DROP TABLE t1
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL>
SQL> CREATE TABLE t1 (a1 INT, b1 INT);

Table created.

SQL>
SQL> ALTER TABLE t1
  2    ADD CONSTRAINT pk_t1_a1 PRIMARY KEY(a1) DISABLE;

Table altered.

SQL>
SQL> ALTER TABLE t1
  2    MODIFY PRIMARY KEY INITIALLY IMMEDIATE
  3      USING INDEX PCTFREE = 30 ENABLE NOVALIDATE;

Table altered.

SQL>
SQL> ALTER TABLE t1
  2    MODIFY PRIMARY KEY ENABLE NOVALIDATE;

Table altered.

SQL>

制約名の変更

変更可能な制約のプロパティの1つは名前です。制約の名前を変更する状況には次のようなものがあります。

  • 表と制約を複製する場合。

    制約名は、複数のスキーマに対しても一意であることが必要です。このため、複製された表の制約を、元の表の制約と同じ名前にすることができません。

  • 制約をデフォルトのシステム生成名で作成したが、使用可能または使用禁止の設定が容易になるように、覚えやすい制約名が必要な場合。

例6-10に、制約のシステム生成名を検索して変更する方法を示します。

例6-10 制約名の変更

SQL> DROP TABLE T;
Table dropped.

SQL> CREATE TABLE T (
  2  C1 NUMBER PRIMARY KEY,
  3  C2 NUMBER);
  4  );

Table created.

SQL> SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS
  2  WHERE TABLE_NAME = 'T'
  3  AND CONSTRAINT_TYPE = 'P';

CONSTRAINT_NAME
------------------------------
SYS_C006075

1 row selected.

SQL> ALTER TABLE T
  2  RENAME CONSTRAINT SYS_C006075
  3  TO T_C1_PK;

Table altered.

SQL> SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS
  2  WHERE TABLE_NAME = 'T'
  3  AND CONSTRAINT_TYPE = 'P';

CONSTRAINT_NAME
------------------------------
T_C1_PK

1 row selected.

SQL>

制約の削除

制約を削除するには、ALTER TABLE文のDROP句を使用します。制約を削除する状況には次のようなものがあります。

1つの制約と、その制約が依存している他のすべての整合性制約を削除するには、CASCADEを指定します。

例6-11 制約の削除

SQL> -- Create table with constraints:
SQL>
SQL> DROP TABLE DeptTab;
DROP TABLE DeptTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> CREATE TABLE DeptTab (
  2    Deptno  NUMBER(3) PRIMARY KEY,
  3    Dname   VARCHAR2(15),
  4    Loc     VARCHAR2(15),
  5    CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc),
  6    CONSTRAINT c_DeptTab_Loc
  7      CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO'))
  8  );

Table created.

SQL> -- Drop constraints:
SQL>
SQL> ALTER TABLE DeptTab
  2    DROP PRIMARY KEY
  3    DROP CONSTRAINT uk_DeptTab_Dname_Loc
  4    DROP CONSTRAINT c_DeptTab_Loc;

Table altered.

SQL>

一意キー、主キーおよび外部キーの各制約を削除する場合は、いくつかの重要な問題および前提条件を認識してください。一意キー制約および主キー制約は、通常、データベース管理者が管理します。


関連項目:

  • ALTER TABLE文のDROP句の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

  • 制約の削除の詳細は、『Oracle Database管理者ガイド』を参照してください。

  • DROP TABLE文のCONSTRAINTS句の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。この方法では、削除される表の主キーと一意キーを参照するすべての参照整合性制約が削除されます。


外部キー制約の管理

外部キー制約は、異なる表の列同士の関連を規定します。したがって、参照中の主キーまたは一意キーの制約が存在していないか、または使用可能になっていない場合は、制約を使用可能にできません。

外部キー列のデータ型および名前

依存する側の表と参照される側の表の対応する列は、同じデータ型である必要があります。列名が一致する必要はありません。

複合外部キーにおける列の制限

外部キーは、親表の主キーまたは一意キーを参照し、主キー制約および一意キー制約は索引を使用して施行されるため、複合外部キーは32列以内に制限されています。

デフォルトでの外部キーの主キー参照

外部キー制約(単一列または複合列)を定義するときにREFERENCESオプションに列リストが指定されていないと、Oracle Databaseは、指定した表の主キーが参照されるものとみなします。または、カッコの中に親表で参照する列を明示的に指定できます。この列リストが親表の主キーまたは一意キーを参照するかどうかは、Oracle Databaseによって自動的に確認されます。参照していない場合は、エラー情報が戻されます。

外部キー制約の作成に必要な権限

外部キー制約を作成するには、制約の作成者に親表および子表に対するアクセス権限が必要です。

  • 親表 参照整合性制約の作成者は、親表を所有するか、または親表の親キーを構成する列に対するREFERENCESオブジェクト権限が必要です。

  • 子表 参照整合性制約の作成者は、表を作成する権限(CREATE TABLEまたはCREATE ANY TABLEシステム権限)または子表を変更する権限(子表のALTERオブジェクト権限またはALTER ANY TABLEシステム権限)が必要です。

どちらの場合も、必要な権限をロールを介して取得することはできません。権限は、明示的に制約の作成者に付与する必要があります。

これらの制限によって、次のことが可能となります。

  • 子表の所有者は、施行される制約の種類、または制約を作成できる他のユーザーを、明示的に決定できます。

  • 親表の所有者は、外部キーが所有者自身の表の主キーおよび一意キーに依存可能であるかどうかを明示的に決定できます。

外部キーによる参照整合性の施行方法の選択

Oracle Databaseでは、外部キー制約の定義の指定どおりに、異なるタイプの参照整合性アクションを施行できます。

  • 親キーの削除または更新の回避 このデフォルト設定を指定すると、キーを参照する行が子表内にある場合、親キーが削除または更新されることはありません。次に例を示します。

    CREATE TABLE Emp_tab (
      FOREIGN KEY (Deptno) REFERENCES Dept_tab);
    
    
  • 親キー削除時の子である行の削除 ON DELETE CASCADEアクションを指定すると、子表が参照する親キーのデータを削除できます。ただし、更新はできません。親キー内のデータが削除されると、削除された親キー値に依存する子表のすべての行も削除されます。この参照アクションを指定するには、外部キー制約の定義にON DELETE CASCADEオプションを指定します。次に例を示します。

    CREATE TABLE Emp_tab (
      FOREIGN KEY (Deptno) REFERENCES Dept_tab
        ON DELETE CASCADE);
    
  • 親キー削除時の外部キーへのNULL設定 ON DELETE SET NULLアクションを指定すると、親キーを参照するデータを削除できます。ただし、更新はできません。親キー内の参照データが削除されると、削除された親キー値に依存する子表内のすべての行の外部キーがNULLに設定されます。この参照アクションを指定するには、外部キー制約の定義にON DELETE SET NULLオプションを指定します。次に例を示します。

    CREATE TABLE Emp_tab (
        FOREIGN KEY (Deptno) REFERENCES Dept_tab
            ON DELETE SET NULL);
    

制約に関する情報の表示

制約の名前、影響がある列および制約の管理に有効な他の情報を検索するには、例6-12のように静的データ・ディクショナリ・ビュー*_CONSTRAINTSおよび*_CONS_COLUMNSに問い合せます。


関連項目:

*_CONSTRAINTSおよび*_CONS_COLUMNSの詳細は、『Oracle Databaseリファレンス』を参照してください。

例6-12 制約に関する情報の表示

SQL> DROP TABLE DeptTab;
DROP TABLE DeptTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> CREATE TABLE DeptTab (
  2    Deptno  NUMBER(3) PRIMARY KEY,
  3    Dname   VARCHAR2(15),
  4    Loc     VARCHAR2(15),
  5    CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc),
  6    CONSTRAINT c_DeptTab_Loc
  7      CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO'))
  8  );

Table created.

SQL> DROP TABLE EmpTab;
DROP TABLE EmpTab
           *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> CREATE TABLE EmpTab (
  2    Empno    NUMBER(5) PRIMARY KEY,
  3    Ename    VARCHAR2(15) NOT NULL,
  4    Job      VARCHAR2(10),
  5    Mgr      NUMBER(5) CONSTRAINT r_EmpTab_Mgr
  6               REFERENCES EmpTab ON DELETE CASCADE,
  7    Hiredate DATE,
  8    Sal      NUMBER(7,2),
  9    Comm     NUMBER(5,2),
 10    Deptno   NUMBER(3) NOT NULL
 11      CONSTRAINT r_EmpTab_Deptno REFERENCES DeptTab
 12  );

Table created.

SQL>
SQL> -- Format columns (optional):
SQL>
SQL> COLUMN CONSTRAINT_NAME   FORMAT A20;
SQL> COLUMN CONSTRAINT_TYPE   FORMAT A4 HEADING 'TYPE';
SQL> COLUMN TABLE_NAME        FORMAT A10;
SQL> COLUMN R_CONSTRAINT_NAME FORMAT A17;
SQL> COLUMN SEARCH_CONDITION  FORMAT A40;
SQL> COLUMN COLUMN_NAME       FORMAT A12;
SQL>
SQL> -- List your accessible constraints in DeptTab and EmpTab:
SQL>
SQL> SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, R_CONSTRAINT_NAME
  2    FROM USER_CONSTRAINTS
  3      WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB')
  4        ORDER BY CONSTRAINT_NAME;

CONSTRAINT_NAME      TYPE TABLE_NAME R_CONSTRAINT_NAME
-------------------- ---- ---------- -----------------
C_DEPTTAB_LOC        C    DEPTTAB
R_EMPTAB_DEPTNO      R    EMPTAB     SYS_C006286
R_EMPTAB_MGR         R    EMPTAB     SYS_C006290
SYS_C006286          P    DEPTTAB
SYS_C006288          C    EMPTAB
SYS_C006289          C    EMPTAB
SYS_C006290          P    EMPTAB
UK_DEPTTAB_DNAME_LOC U    DEPTTAB

8 rows selected.

SQL>
SQL> -- Distinguish between NOT NULL and CHECK constraints
SQL> -- in DeptTab and EmpTab:
SQL>
SQL> SELECT CONSTRAINT_NAME, SEARCH_CONDITION
  2    FROM USER_CONSTRAINTS
  3      WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB')
  4         AND CONSTRAINT_TYPE = 'C'
  5           ORDER BY CONSTRAINT_NAME;

CONSTRAINT_NAME      SEARCH_CONDITION
-------------------- ----------------------------------------
C_DEPTTAB_LOC        Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')
SYS_C006288          "ENAME" IS NOT NULL
SYS_C006289          "DEPTNO" IS NOT NULL

3 rows selected.

SQL>
SQL> -- For DeptTab and EmpTab, list columns that constitute constraints:
SQL>
SQL> SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME
  2    FROM USER_CONS_COLUMNS
  3      WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB')
  4        ORDER BY CONSTRAINT_NAME;

CONSTRAINT_NAME      TABLE_NAME COLUMN_NAME
-------------------- ---------- ------------
C_DEPTTAB_LOC        DEPTTAB    LOC
R_EMPTAB_DEPTNO      EMPTAB     DEPTNO
R_EMPTAB_MGR         EMPTAB     MGR
SYS_C006286          DEPTTAB    DEPTNO
SYS_C006288          EMPTAB     ENAME
SYS_C006289          EMPTAB     DEPTNO
SYS_C006290          EMPTAB     EMPNO
UK_DEPTTAB_DNAME_LOC DEPTTAB    LOC
UK_DEPTTAB_DNAME_LOC DEPTTAB    DNAME

9 rows selected.

SQL>

次のことに注意してください。

次の項目は、SEARCH_CONDITION列に明示的にリストされます。