データ整合性
この章では、整合性制約によって、データベースに関連するビジネス・ルールがどのように規定され、表への無効なエントリがどのように防止されるかについて説明します。
-
データ整合性の概要データにおいては、データベース管理者やアプリケーション開発者が決定したビジネス・ルールに準拠し、データ整合性を維持するのは重要なことです。
-
整合性制約のタイプOracle AI Databaseでは、表と列レベルの両方で制約を適用できます。また、複数の表を含むアサーションも適用できます。
-
整合性制約とアサーションの状態制約定義またはアサーション定義の一部として、Oracle AI Databaseで制約またはアサーションを適用する方法とタイミングを指定して、制約またはアサーションの状態を判断できます。列の背景と整合性制約の必要性は、「表の概要」を参照してください。
データ整合性の概要
データにおいては、データベース管理者やアプリケーション開発者が決めたビジネス・ルールに準拠した、データ整合性が維持されていることが重要です。
ビジネス・ルールには、常にtrueまたは常にfalseになる必要がある条件および関係を指定します。たとえば、各企業では、給与、従業員番号、在庫追跡などに関して独自のポリシーを定義します。
-
データ整合性を保証する手法データベース・アプリケーションの設計時に、データベースに格納するデータの整合性を保証するために開発者が選択できるオプションはいくつかあります。
-
整合性制約の利点整合性制約は、SQLを使用して作成および削除されるスキーマ・オブジェクトです。データの整合性を維持するために、可能な場合は常に整合性制約またはアサーションを使用します。
データ整合性を保証する方法
データベース・アプリケーションを設計する場合、開発者は、データベースに格納するデータの整合性を保証するためのいくつかのオプションを使用できます。
オプションは次のとおりです。
-
トリガーされるストアド・データベース・プロシージャを使用して、ビジネス・ルールを規定します
-
ストアド・プロシージャを使用してデータへのアクセスを完全に制御します
-
データベース・アプリケーションのコードでビジネス・ルールを規定します。
-
列またはオブジェクト・レベルで定義される、データベースの値を制限する規則、Oracle AI Databaseの整合性制約を使用します。
-
アサーションの使用(アプリケーションのデータベース表の副問合せを含むブール式)
関連情報:
-
「トリガーの概要」では、トリガーの目的およびタイプについて説明します
-
「サーバー側プログラミングの概要」では、ストアド・プロシージャの目的および特性について説明します
整合性制約の利点
整合性制約は、SQLを使用して作成および削除されるスキーマ・オブジェクトです。データの整合性を維持するために、可能な場合は常に整合性制約またはアサーションを使用します。
データの整合性を維持する方法として、整合性制約とアサーションには、次のような利点があります。
-
宣言の容易さ
SQL文を使用して整合性制約およびアサーションを定義するため、表を定義または変更するときに追加のプログラミングは必要ありません。SQL文は記述が容易で、プログラミングのエラーを避けられます。
-
規則の集中化
整合性制約およびアサーションは表に対して定義され、データ・ディクショナリに格納されます。したがって、すべてのアプリケーションによって入力されるデータは、同じ整合性制約とアサーションを遵守する必要があります。規則が表レベルで変化した場合も、アプリケーションを変更する必要はありません。また、データベースによってSQL文がチェックされる前に、アプリケーションがデータ・ディクショナリのメタデータを使用して、すぐにユーザーに違反を通知することもできます。
-
データをロードする場合の柔軟性
大量のデータをロードする場合は、パフォーマンスのオーバーヘッドを回避するために、整合性制約とアサーションを一時的に無効にできます。データ・ロードが完了したら、整合性制約とアサーションを再度有効にできます。
関連情報:
-
データの整合性を維持する方法を学習するには、『Oracle AI Database Oracle AI Database開発スタート・ガイド』および『Oracle AI Database開発ガイド』を参照してください
-
整合性制約の管理方法を学習するには、Oracle AI Database管理者ガイドを参照
整合性制約のタイプ
Oracle AI Databaseでは、表レベルと列レベル、および複数の表を含むアサーションの両方で制約を適用できます。
列または属性の一部として指定される制約が、表内指定です。表定義の一部として指定される制約が、表外指定です。
キーとは、特定タイプの整合性制約の定義に含まれる列または列の集合のことです。キーによって、リレーショナル・データベースの表と列の間の関連が示されます。キーの中にある個々の値を、キー値と呼びます、
次の表に、制約のタイプを示します。表内指定であることが必要なNOT NULLを除き、どの制約も表内と表外のいずれかで指定できます。
表1整合性制約のタイプ
| 制約タイプ | 摘要 | 参照 |
|---|---|---|
NOT NULL |
指定した列でのNULLを含む行の挿入または更新を許可または禁止します。 | 「NOT NULL整合性制約」 |
| 一意キー | 同じ列または列の組合せで、複数の行が同じ値を持つことを禁止しますが、一部の値がNULLであることを許可します。 | 一意制約 |
| 主キー | NOT NULL制約と一意制約を結合します。これにより、同じ列または列の組合せで、複数の行が同じ値を持つことを禁止し、値がNULLであることを禁止します。 |
「主キー制約」 |
| 外部鍵 | 列を外部キーとして指定し、外部キーと、参照キーと呼ばれる主キーまたは一意キーの間の関係を確立する。 | 外部キーの制約に関する項 |
| 小切手 | 指定した条件をデータベース値が満たしている必要があります。 | 「チェック制約」 |
REF |
REF列の値で許可されるデータ操作のタイプ、およびその操作の結果として依存データが受ける影響について指示します。オブジェクト・リレーショナル・データベースでは、REFと呼ばれる組込みデータ型によって、指定したオブジェクト型の行オブジェクトへの参照がカプセル化されます。REF列に対する参照整合性制約によって、REFの行オブジェクトがあることが保証されます。 |
REF制約について学習するには、『Oracle AI Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください |
Assertions |
アサーションは、アプリケーションのデータベース表に対する副問合せを含むブール式です。アサーションには制約のセマンティクスがあります。つまり、トランザクションがデータを変更し、これらの変更をコミットしている間に、これらのブール式の真相を確認するためにデータベースが割り当てられます。 | アサーションについて学習するには、「SQLアサーション」を参照してください |
-
NOT NULL整合性制約
NOT NULL制約の場合は、表の列にNULL値を含めることができません。NULLは、値がないことを示します。デフォルトでは、表内のすべての列でNULLを使用できます。 -
一意制約一意キー制約では、1つの列または列セット内のすべての値を一意にする必要があります。1つの表の行では、列(一意キー)または列の集合(コンポジット一意キー)で重複した値を持つことはありません。
-
主キー制約 主キー制約では、この制約の対象となる1つ以上の列グループの値によって、行が一意に識別されます。各表には1つの主キーを設定でき、この主キーにより行が識別され、行が重複しないことが保証されます。
-
外部キー制約2つの表に1つ以上の共通の列が含まれる場合、Oracle AI Databaseでは、外部キー制約(参照整合性拘束とも呼ばれる)によって2つの表の間の関係を規定できます。
-
チェック制約列(または列の集合)に対してチェック制約がある場合は、各行で、指定した条件がTRUEまたはUNKNOWSであることが必要です。
-
事前チェック可能なCHECK制約
PRECHECKとマークされたチェック制約はデータベースの外部でチェックできます。 -
アサーション・アサーションは、アプリケーションのデータベース表の副問合せを含むブール式です。
関連情報:
-
制約のタイプについてさらに学習するには、Oracle AI Database SQL言語リファレンスを参照してください。
NOT NULL整合性制約
NOT NULL制約がある場合、表の列値にNULLを使用できません。NULLは、値がないことを示します。デフォルトでは、表内のすべての列でNULLを使用できます。
NOT NULL制約は、値が必須である列のためのものです。たとえば、hr.employees表ではemail列に値が必要です。電子メール・アドレスなしで従業員の行を挿入しようとすると、次のエラーが発生します。
SQL> INSERT INTO hr.employees (employee_id, last_name) values (999, 'Smith');
.
.
.
ERROR at line 1:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMAIL")
NOT NULL制約付きの列を追加できるのは、表に行が1つも含まれていない表またはデフォルト値が指定された場合のみです。
関連情報:
-
NOT NULL制約を表に追加する例は、『Oracle AI Database Oracle AI Database開発スタート・ガイド』を参照してください -
NOT NULL制約を使用する場合の制限については、『Oracle AI Database SQL言語リファレンス』を参照してください -
NOT NULL制約を使用するかどうかを学習するには、『Oracle AI Database開発ガイド』を参照
一意制約
一意キー制約では、列(または列の集合)のすべての値が一意である必要があります。 一意キーの制約を設定されていると、表の行では、列(一意キー)または列の集合(コンポジット一意キー)で重複した値を持つことはありません。
ノート: キーという用語は、整合性制約で定義されている列のみを指します。データベースではキー列に対して索引を暗黙的に作成または再利用することで一意制約を規定するため、一意キーという用語は一意キー制約または一意索引のシノニムとして誤用されることがあります。
一意キー制約は、値の重複が許されない列に適しています。一意制約は、(各表の行を一意に識別することが目的である)主キー制約とは異なり、通常は、一意であること以外の意味を持たない値が含まれています。一意キーの例には次のものがあります。
-
主キーが顧客番号である場合の、顧客電話番号
-
主キーが部門番号である場合の、部門名
例4-1に示すように、hr.employees表のemail列には一意キー制約が存在します。文の関連する部分は、次のとおりです。
CREATE TABLE employees ( ...
, email VARCHAR2(25)
CONSTRAINT emp_email_nn NOT NULL ...
, CONSTRAINT emp_email_uk UNIQUE (email) ... );
次の例に示すように、emp_email_uk制約により、2人の従業員が同じ電子メール・アドレスを持つことはありません。
SQL> SELECT employee_id, last_name, email FROM employees WHERE email = 'PFAY';
EMPLOYEE_ID LAST_NAME EMAIL
----------- ------------------------- -------------------------
202 Fay PFAY
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)
1 VALUES (999,'Fay','PFAY',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMAIL_UK) violated
NOT NULL制約も定義されている場合を除き、一意キー制約では、NULLは常に許可されます。このため、一意キー制約とNOT NULL制約の両方を持つ列が一般的に使用されます。これらの組合せにより、ユーザーは一意キーに必ず値を入力することになり、さらに新しい行データが既存の行データと競合することがなくなります。
ノート:複数の列に対する一意キー制約の検索メカニズムにより、一部がnullのコンポジット一意キー制約の非NULL列で同一の値は許されない。
例7-1 一意制約
SQL> SELECT employee_id, last_name, email FROM employees WHERE email = 'PFAY';
EMPLOYEE_ID LAST_NAME EMAIL
----------- ------------------------- -------------------------
202 Fay PFAY
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)
1 VALUES (999,'Fay','PFAY',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMAIL_UK) violated
関連情報:
主キー制約
主キー制約では、制約の対象となる1つ以上の列グループの値によって、行が一意に識別されます。各表には1つの主キーを設定でき、この主キーにより行が識別され、行が重複しないことが保証されます。
主キーには、自然キーまたはサロゲート・キーを使用できます。自然キーは、表内の既存の属性から作成された、意味のある識別子です。たとえば、参照表の郵便番号を自然キーとして使用できます。
これに対し、サロゲート・キーは、システムで生成され、データが増加する識別子であり、表内での一意性が保証されます。通常、sequenceまたは UUIDはサロゲートキーを生成します。
Oracle AI Databaseでは、主キー制約の実装により、次のことが保証されます。
-
指定された列または列の集合の中に、2つの行が重複する値を持つことはありません。
-
主キー列では、NULLは許可されません。
主キーが必要となる典型的な状況は、従業員用の数値識別子です。各従業員は一意のIDを持つ必要があります。従業員は、employees表の1つの行によってのみ記述する必要があります。
「一意制約」の例では、既存の従業員が従業員IDとして202を持っており、従業員IDが主キーであることが示されています。次に示す例では、同じ従業員IDを持つ従業員、およびIDを持たない従業員を追加します。
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)
1 VALUES (202,'Chan','JCHAN',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMP_ID_PK) violated
SQL> INSERT INTO employees (last_name) VALUES ('Chan');
.
.
.
ERROR at line 1:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMPLOYEE_ID")
データベースにより、索引を持つ主キー制約は規定されます。通常、列に対して作成された主キー制約によって、暗黙的に一意索引とNOT NULL制約が作成されます。この規則には、次の例外がある点に注意してください。
-
場合によっては、遅延可能制約で主キーを作成する場合、生成された索引は一意ではありません。
ノート:
CREATE UNIQUE INDEX文では、一意の索引が明示的に作成できます。 -
主キー制約の作成時に使用可能な索引がある場合、制約ではこの索引を再利用し、暗黙的に作成することはありません。
デフォルトでは、暗黙的に作成された索引の名前が、主キー制約の名前になります。索引にはユーザー定義名を指定することもできます。制約の作成に使用するCREATE TABLE文またはALTER TABLE文にENABLE句を組み込んで、索引の記憶域オプションを指定できます。
関連項目:表に主キー制約を追加する方法を学習するには、『Oracle AI Database Oracle AI Database開発スタート・ガイド』および『Oracle AI Database開発ガイド』を参照してください
外部キーの制約
2つの表に1つ以上の共通の列が含まれる場合、Oracle AI Databaseでは、参照整合性拘束とも呼ばれる外部キー制約を介して2つの表の間の関係を規定できます。
外部キー制約では、制約が定義される列の各値に対して、他の表と列を指定するもう一方の列の値が一致する必要があります。参照整合性規則の例としては、既存の部門にのみ従事できる従業員があります。
次の表に、参照整合性制約に関連する用語を示します。
表2参照整合性制約の用語
| 用語 | 定義 |
|---|---|
| 外部鍵 | 制約の定義に含まれている列または列の集合のうち、参照キーを参照します。たとえば、 外部キーは、複数列として定義できます。ただし、コンポジット外部キーの列数とデータ型は、参照先のコンポジット主キーまたは一意キーと同じであることが必要です。 外部キーの値は、参照先の主キーまたは一意キーの値と一致するか、NULLであることが可能です。コンポジット外部キーのいずれかの列がNULLの場合、そのキーのNULL以外の部分は、親キーの対応部分と一致している必要はありません。 |
| 参照されたキー | 表の一意キーまたは主キーで、外部キーによって参照されるキー。たとえば、departmentsのdepartment_id列は、employeesのdepartment_id列の参照キーです。 |
| 依存表または子表 | 外部キーを含む表。この表は、参照される一意キーまたは主キーにある値に依存しています。たとえば、employees表はdepartmentsの子です。 |
| 参照表または親表 | 子表の外部キーが参照する表。この表の参照キーにより、子表に対する特定の挿入または更新が許可されるかどうかが決まります。たとえば、departments表はemployeesの親です。 |
図7-1に、employees.department_id列の外部キーを示します。この列のすべての値が、departments.department_id列の値と一致することが保証されます。このため、employees.department_id列に間違った部門番号が存在することはありません。
図1: 参照整合性制約

-
自己参照型整合性制約 自己参照型整合性制約とは、同じ表の親キーを参照する外部キーのことです。
-
NULLと外部キーリレーショナル・モデルでは、外部キーの値は、参照先の主キーまたは一意キーの値と一致するか、NULLであることが可能です。たとえば、
hr.employeesの行で部門IDが指定されないことがあります。 -
親キーの修正と外部キー外部キーと親キーの関係は、親キーの削除に影響を及ぼします。たとえば、あるユーザーが部門のレコードの削除を試行すると、この部門の従業員のレコードに何が起こるかについて説明します。
-
索引と外部キー通常、外部キーには索引付けが必要です。唯一の例外は、対応する一意キーまたは主キーの更新や削除が発生しないことが確実な場合です。関連項目:表に外部キー制約を追加する方法を学習するには、『Oracle AI Database Oracle AI Database開発スタート・ガイド』および『Oracle AI Database開発ガイド』を参照してください
自己参照型整合性制約
自己参照型整合性制約とは、同じ表の親キーを参照する外部キーのことです。
次の図では、自己参照型制約によって、employees.manager_id列のすべての値が、employees.employee_id列の既存の値に対応するようになります。たとえば、従業員102の管理職がemployees表に存在する必要があります。この制約によって、間違った従業員番号がmanager_id列に存在する可能性がなくなります。
図2: 単一表の参照制約

NULLと外部キー
リレーショナル・モデルでは、外部キーの値は、参照先の主キーまたは一意キーの値と一致するか、NULLであることが可能です。たとえば、hr.employeesの行で部門IDが指定されないことがあります。
コンポジット外部キーのいずれかの列がNULLの場合、そのキーのNULL以外の部分は、親キーの対応部分と一致している必要はありません。たとえば、reservations表のtable_id列およびdate列にはコンポジット外部キーが含まれるが、table_idはNULLであることがあります。
親キーの修正と外部キー
親キーを削除するとき、外部キーと親キーの間の関係が影響を及ぼします。たとえば、あるユーザーが部門のレコードの削除を試行すると、この部門の従業員のレコードに何が起こるかについて説明します。
親キーが変更された場合、参照整合性制約では、子表の依存行に対して実行される次のアクションを指定できます。
-
削除または更新に対するアクションなし
通常、結果が参照整合性に違反する場合、ユーザーは参照キー値を変更できません。たとえば、
employees.department_idがdepartmentsに対する外部キーであり、従業員が特定の部門に属す場合、この部門の行の削除を試行すると、制約に対する違反が発生します。 -
カスケードの削除
参照キー値を含む行が削除された場合、子表の内部で依存している外部キー値を含むすべての行も削除されます(
DELETE CASCADE)。たとえば、departmentsの行を削除すると、この部門のすべての従業員の行が削除されます。 -
NULLを設定する削除
参照キー値を含む行が削除された場合に、子表のうち依存している外部キー値を含むすべての行の値がNULLに設定されます(
DELETE SET NULL)。たとえば、部門の行を削除すると、この部門のすべての従業員に関してdepartment_id列値がNULLに設定されます。
表7-3に、親表のキー値および子表の外部キー値に対する異なる参照アクションごとに可能なDML文の概要を示します。
表3更新NO ACTIONとDELETENO ACTIONで許可されるDML文
| DML文 | 親表に対して発行 | 子表に対して発行 |
|---|---|---|
INSERT |
親キー値が一意であれば常に発行できます。 | 外部キーの値が親キーに存在するか、外部キーの一部またはすべてがNULLの場合にのみ発行できます。 |
UPDATE NO ACTION |
文の実行後に、参照される親キー値のない行が子表内に残らない場合は発行できます。 | 文の実行後も新しい外部キー値によって参照キー値が参照される場合は発行できます。 |
DELETE NO ACTION |
子表のどの行も親キー値を参照していない場合は発行できます。 | 常に発行可能 |
DELETE CASCADE |
常に発行可能 | 常に発行可能 |
DELETE SET NULL |
常に発行可能 | 常に発行可能 |
ノート: Oracle DatabaseのFOREIGN KEY整合性制約でサポートされていないその他の参照アクションは、データベース・トリガーを使用して強制できます。「トリガーの概要」を参照してください。
ON DELETE句について学習するには、関連項目: 『Oracle AI Database SQL言語リファレンス』を参照してください。
索引と外部キー
通常、外部キーには索引付けが必要です。唯一の例外は、対応する一意キーまたは主キーの更新や削除が発生しないことが確実な場合です。
子表で外部キーの索引付けを行うと、次の利点があります。
-
子表に対する完全表ロックが防止されます。かわりに、データベースは索引に対する行ロックを取得します。
-
子表の全表スキャンを行う必要が排除されます。例として、ユーザーが
departments表から部門10のレコードを削除する場合を想定します。employees.department_idが索引付けされていない場合、データベースはemployeesをスキャンして、部門10に従業員が存在するかを確認する必要があります。
関連情報:
-
「ロックと外部キー」では、索引付き外部キーおよび索引なしの外部キー列のロック動作について説明します
-
「索引の概要」では、索引の目的および特性について説明します。
制約のチェック
列または列の集合に対するチェック制約では、すべての行に対して、指定した条件がTRUEまたはUNKNOWSであることが必要です。
DMLの結果で制約の条件がFALSEに評価される場合、そのSQL文はロールバックされます。チェック制約の主な利点は、特殊な整合性規則を規定できることです。たとえば、チェック制約を使用すると、hr.employees表に次の規則を規定できます。
-
salary列の値は10000以下である必要があります。 -
commission列の値は、salaryの値以下である必要があります。
次の例では、employeesに最大給与制約を作成し、最大値を超える給与を含む行を文で挿入すると、どのようなことが起こるかを示します。
SQL> ALTER TABLE employees ADD CONSTRAINT max_emp_sal CHECK (salary < 10001);
SQL> INSERT INTO employees (employee_id,last_name,email,hire_date,job_id,salary)
1 VALUES (999,'Green','BGREEN',SYSDATE,'ST_CLERK',20000);
.
.
.
ERROR at line 1:
ORA-02290: check constraint (HR.MAX_EMP_SAL) violated
1つの列に、定義された列を参照する複数のチェック制約を設定できます。たとえば、salary列には、10000より大きい値を禁止する1つの制約と、500未満の値を禁止する別の制約を設定できます。
単一の列に対して複数のチェック制約が存在する場合は、その目的が競合しないように設計する必要があります。また、条件は特定の順序では評価されません。データベースでは、チェック条件が矛盾しないかどうかは検証されません。
チェック制約の制限について学習するには、関連項目: 『Oracle AI Database SQL言語リファレンス』
事前チェック可能なCHECK制約
PRECHECKとマークされたチェック制約をデータベースの外部でチェックできます。
表の作成または変更中に、チェック制約をPRECHECK状態に設定します。PRECHECK状態は制約のENABLEおよびVALIDATE状態を補完するもので、3つすべての状態を同時にアクティブにできます。
JSONを使用してチェック制約を表す場合、Oracle AI Databaseでは、JSONスキーマのエクスポートおよびアプリケーション・クライアント内のJSONスキーマ・バリデータに対するJSONデータの検証ができます。制約がPRECHECK状態に設定されている場合、制約には、制約のセマンティクスを保持する同等のJSONスキーマが存在することを示します。クライアント・アプリケーション開発者は、クライアント・アプリケーション内で制約を事前検証できます。データベースにより制約がチェックされ、JSONスキーマで制約を表現できない場合はエラーが生成されます。
関連項目
アサーション
アサーションは、アプリケーションのデータベース表に対する副問合せを含むブール式です。
アサーションには制約のセマンティクスがあります。つまり、トランザクションがデータを変更し、これらの変更をコミットしている間に、これらのブール式の真相を確認するためにデータベースが割り当てられます。
次のSQL文は、NO_TRAINERS_IN_BOSTONというアサーションを作成し、ボストン・ベースの部門で採用されたトレーナがないことを要求します。最上位レベルのNOT EXISTSは、EMP表とDEPT表間の結合の結果セットを空のままにすることを要求するブール式を表します。
CREATE ASSERTION no_trainers_in_boston CHECK
(NOT EXISTS
(SELECT 'trainer in Boston'
FROM emp e, dept d
WHERE e.deptno = d.deptno
AND e.job = 'TRAINER'
AND d.loc = 'BOSTON'));
アサーションはスキーマ・レベルのオブジェクトです。これは、他のスキーマの表がブール式によって参照される場合、それらの表にアクセスするためにASSERTION REFERENCESオブジェクト権限が必要であることを意味します。これは、2つのスキーマにまたがる外部キーとは異なります。つまり、異なるスキーマ内の表の主キーを指す外部キーを正常に作成するには、REFERENCESオブジェクト権限が必要です。
アサーションは、一般的なデータ整合性制約です。CHECK制約、PRIMARY KEY制約、UNIQUE制約およびFOREIGN KEY制約を置換するために使用できます。
たとえば、EMP表で次の制約があるとします。
-
CHECK (COMM <= SAL) -
PRIMARY KEY (EMPNO) -
UNIQUE (ENAME, DEPTNO) -
FOREIGN KEY (DEPTNO) REFERENCES DEPT(DEPTNO)
これらの制約は、次のアサーションを使用して実装できます。
CREATE ASSERTION commission_not_greater_than_salary CHECK
(NOT EXISTS
(SELECT ''
FROM emp e
WHERE e.comm > e.sal));
CREATE ASSERTION emp_empno_pk CHECK
(NOT EXISTS
(SELECT ''
FROM emp e1, emp e2
WHERE e1.empno = e2.empno
AND e1.rowid != e2.rowid));
CREATE ASSERTION emp_ename_deptno_uk CHECK
(NOT EXISTS
(SELECT ''
FROM emp e1, emp e2
WHERE e1.ename = e2.ename
AND e1.deptno = e2.deptno
AND e1.rowid != e2.rowid));
CREATE ASSERTION emp_fk_dept CHECK
(NOT EXISTS
(SELECT ''
FROM emp e
WHERE NOT EXISTS
(SELECT ''
FROM dept d
WHERE d.deptno = e.deptno)));
ただし、可能なかぎり常に制約を使用し、制約を使用できない場合にのみアサーションを使用することを強くお薦めします。
関連項目
整合性制約およびアサーションの状態
制約定義またはアサーション定義の一部として、Oracle AI Databaseがいつどのようにして制約またはアサーションを規定するかを指定できます。これにより、制約状態またはアサーション状態が決定されます。
-
変更されたデータと既存のデータのチェックデータベースでは、制約またはアサーションが既存のデータに適用されるか将来のデータに適用されるかどうかを指定できます。制約またはアサーションが使用可能である場合、データベースでは、入力または更新された時点における新規データがチェックされます。制約またはアサーションに準拠しないデータをデータベースに入力することはできません。
-
データベースが制約の妥当性をチェックするタイミングすべての制約とアサーションが、遅延不可(デフォルト)または遅延可能状態のどちらかになっています。この状態によって、Oracle AI Databaseが妥当性を確認するためにどの時点制約またはアサーションをチェックしますかが決まります。
-
制約チェックおよびアサーション・チェックの例次の例では、Oracle AI Databaseで制約のチェックがいつ実行されるかを示します。
変更されたデータおよび既存のデータのチェック
データベースでは、制約またはアサーションが既存のデータまたは将来のデータに適用されるかどうかを指定できます。制約またはアサーションが使用可能である場合、データベースでは、入力または更新された時点における新規データがチェックされます。制約またはアサーションに準拠しないデータをデータベースに入力することはできません。
たとえば、employees.department_idに対してNOT NULL制約を使用可能にすると、将来のすべての行が部門IDを持ちます。制約が使用禁止である場合、表には制約に違反する行を入力できます。
制約とアサーションは、次のいずれかの検証モードに設定できます。
-
VALIDATE既存のデータは制約またはアサーションに準拠する必要があります。たとえば、
employees.department_idに対してNOT NULL制約を使用可能にし、この制約をVALIDATEに設定すると、既存のすべての行が部門IDを持つことをチェックできます。 -
NOVALIDATE既存のデータは制約またはアサーションに準拠する必要がありません。実際には、これは"信頼"モードです。たとえば、表にロードされたすべての売上に日付がある場合、日付列に
NOT NULL制約を作成し、制約をNOVALIDATEに設定できます。適用されない制約は、通常、マテリアライズド・ビューおよびクエリー・リライトにのみ有効です。NOVALIDATEモードの制約の場合、RELYパラメータは、オプティマイザが制約を使用して結合情報を判別できることを示します。制約はデータの検証には使用されませんが、マテリアライズド・ビューのより高度なクエリー・リライトを可能にし、データ・ウェアハウス・ツールによってデータ・ディクショナリから制約情報を取得できます。デフォルトはNORELYです。これは、オプティマイザが実際には制約を認識しないことを意味します。
VALIDATEおよびNOVALIDATEの動作は、常に、制約またはアサーションが使用可能であるか使用禁止であるかどうかによって異なります。次の表に関係をまとめます。
表4変更されたデータのチェックおよび既存のデータのチェック
| 変更済データ | 既存のデータ | 要約 |
|---|---|---|
ENABLE |
VALIDATE |
既存のデータと将来のデータは制約またはアサーションに準拠する必要があります。データが入力されている表に新しい制約またはアサーションを適用しようとすると、既存の行がこの制約またはアサーションに違反する場合、エラーになります。 |
ENABLE |
NOVALIDATE |
データベースは制約またはアサーションをチェックしますが、制約はすべての行に関してTRUEである必要はありません。したがって、既存の行が制約またはアサーションに違反している可能性はありますが、新しい行または変更された行は規則に準拠する必要があります。このモードは、整合性がすでに検証されている既存のデータを含むデータ・ウェアハウスで使用されます。 |
DISABLE |
VALIDATE |
データベースでは制約が使用禁止になり、索引が削除されて、制約の対象となる列への変更が禁止されます。アサーションをこの状態にすることはできません。 |
DISABLE |
NOVALIDATE |
制約またはアサーションはチェックされず、必ずしもtrueであるとはかぎりません。 |
制約の状態について学習するには、関連項目: Oracle AI Database SQL言語リファレンスを参照してください。
データベースが制約およびアサーションの妥当性チェックを行うタイミング
あらゆる制約とアサーションは、遅延不可(デフォルト)または遅延可能状態のいずれかにいます。この状態によって、Oracle AI Databaseが妥当性を確認するためにどの時点制約またはアサーションをチェックしますかが決まります。
次の図は、遅延可能制約とアサーションのオプションを示しています。
図3: 遅延可能制約とアサーションのオプション

-
遅延不可制約遅延不可制約では、Oracle AI Databaseは、制約またはアサーションの妥当性チェックをトランザクションの最後まで延期することはありません。かわりに、データベースでは各文の最後で制約またはアサーションをチェックします。制約またはアサーションに違反している場合、その文はロールバックします。
-
遅延可能制約とアサーション 遅延可能制約またはアサーションにより、トランザクションで
SET CONSTRAINT句を使用して、COMMIT文が発行されるまでこの制約またはアサーションのチェックを遅延できます。制約またはアサーションに違反している可能性があるデータベースを変更する場合、この設定によって、変更がすべて完了するまで制約またはアサーションを事実上に無効にできます。
遅延不可能な制約とアサーション
遅延不可制約では、Oracle AI Databaseは、制約またはアサーションの妥当性チェックをトランザクションの最後まで延期することはありません。かわりに、データベースでは各文の最後で制約またはアサーションをチェックします。制約またはアサーションに違反している場合、その文はロールバックします。
たとえば、employees.last_name列用に遅延不可のNOT NULL制約が存在します。セッションが姓のない行を挿入しようとすると、NOT NULL制約に違反しているため、データベースはただちに文をロールバックします。行は挿入されません。
遅延可能制約とアサーション
遅延可能制約またはアサーションにより、トランザクションでSET CONSTRAINT句を使用して、COMMIT文が発行されるまでこの制約またはアサーションのチェックを遅延できます。制約またはアサーションに違反している可能性があるデータベースを変更する場合、この設定によって、変更がすべて完了するまで制約またはアサーションを事実上に無効にできます。
データベースが遅延可能制約またはアサーションをチェックする時点に関して、デフォルト動作を設定できます。次の属性のいずれかを指定できます。
-
INITIALLY IMMEDIATEデータベースは、各文の実行直後に制約またはアサーションをチェックします。制約またはアサーションに違反している場合、データベースは文をロールバックします。
-
INITIALLY DEFERREDデータベースは、
COMMITが発行された時点で制約またはアサーションをチェックします。制約またはアサーションに違反している場合、データベースはトランザクションをロールバックします。
employees.last_nameに対する遅延可能なNOT NULL制約がINITIALLY DEFERREDに設定されているとします。ユーザーは100個のINSERT文を含むトランザクションを作成し、その一部にはlast_nameとしてNULL値があります。ユーザーがコミットしようとすると、データベースは100個すべての文をロールバックします。ただし、この制約がINITIALLY IMMEDIATEに設定されている場合、データベースはトランザクションをロールバックしません。
制約によってアクションが発生する場合は、遅延制約か即時制約かに関係なく、このアクションはアクションを発生させた文の一部とみなされます。たとえば、departmentsの行を削除すると、削除された部門の行を参照するemployeesのすべての行が削除されます。この場合、employeesからの削除は、departmentsに対して実行されたDELETE文の一部とみなされます。
関連項目:制約属性とそのデフォルト値の詳細は、『Oracle AI Database SQL言語リファレンス』を参照してください。
制約およびアサーション・チェックの例
次の例では、Oracle AI Databaseで制約とアサーションのチェックをいつ実行するかを示します。
次のようなものがあるとします。
-
employees表は、「自己参照型整合性制約」に示された構造を持っています。 -
自己参照型制約によって、
manager_id列のエントリがemployee_id列の値に依存しています。 -
例: 親鍵値が存在しないときの外部キー列への値の挿入この例では、
employees表に最初の行を挿入する場合について検討します。現在は行が存在しないため、manager_id列の値がemployee_id列の既存の値を参照できない場合に行を入力する方法を考えなくてはなりません。 -
例: すべての外部キー値と親キー値の更新この例では、自己参照型制約によって、
employeesのmanager_id列のエントリがemployee_id列の値に依存します。 -
例: すべてのマネージャが同じ部門に担当者がいる必要があるこの例では、すべてのマネージャが同じ部門に担当者がいることを確認するためのアサーションを作成します。
例: 親キー値が存在しない時点での外部キー列での値の挿入
この例では、employees表に最初の行を挿入する場合を考えます。現在は行が存在しないため、manager_id列の値がemployee_id列の既存の値を参照できない場合に行を入力する方法を考えなくてはなりません。
次の可能性が考えられます。
-
manager_id列にNOT NULL制約が定義されていない場合には、第1行のmanager_id列にnullを入力できます。外部キーではnullが許可されるため、Oracle AI Databaseではこの行を表に挿入します。
-
同じ値を
employee_id列およびmanager_id列に入力でき、これは、その従業員が管理職であることを示します。このことから、Oracle AI Databaseが文の実行後に制約チェックを実行ことがわかります。親キーと外部キーに同じ値を指定した行の入力を許可するために、データベースは、まず新しい行を挿入してから、その新しい行の
manager_idに対応するemployee_idのある行がその表に含まれているかどうかをチェックします。 -
SELECT文のネストを伴うINSERT文など、複数行を挿入するINSERT文により、相互に参照しあう行を挿入できます。たとえば、第1行には従業員IDとして200、管理職IDとして300が含まれており、第2行には従業員IDとして300、管理職IDとして200が含まれているとします。制約チェックは
INSERT文の実行が完了するまで遅延されています。すべての行が挿入されてから、制約違反がないかどうかすべての行がチェックされます。
デフォルト値は、文の解析前にINSERT文の一部として組み込まれます。このため、デフォルトの列値はすべての整合性制約チェックの対象になります。
例: すべての外部キー値および親キー値の更新
この例では、自己参照型制約によって、employeesのmanager_id列のエントリがemployee_id列の値に依存します。
会社が買収された場合です。この買収に伴い、すべての従業員番号の現在の設定値に5000を加算して、新しい会社の従業員番号と調和させる必要があります。次の図に示すように、一部の従業員は管理職でもあります。
図4: 更新前のemployees表

管理職番号は従業員番号でもあるため、管理職番号にも5000を加算する必要があります。次のSQL文を実行すると値を更新できます。
UPDATE employees SET employee_id = employee_id + 5000,
manager_id = manager_id + 5000;
制約は、各manager_id値がemployee_id値と一致するかどうかを検証するように定義されていますが、データベースでは文の完了後に制約チェックが効率的に実行されるため、前述の文は有効です。図7-5に、データベースでは、制約をチェックする前に、SQL文全体のアクションが実行されていることを示します。
図5: 制約チェック

この項の例は、INSERT文とUPDATE文を実行した場合の制約チェックのメカニズムを示していますが、データベースでは同じメカニズムがすべてのタイプのDML文に使用されます。同じメカニズムが、自己参照型制約のみでなく、すべてのタイプの制約に使用されます。ノート: ビューまたはシノニムに対する処理は、実表に定義されている整合性制約に従います。
例: すべてのマネージャが同じ部門に事務員を持つ必要がある
この例では、すべてのマネージャが同じ部門に担当者がいることを確認するアサーションを作成します。
この例では、最初に事務員を挿入し、次にマネージャを挿入する必要があります。複数の行挿入を実行する場合、制約と同様に、各INSERT文の実行後にアサーションが検証されます。このアサーションをDEFERRABLEに設定して、最初にマネージャを挿入し、次に事務員を挿入できるようにすることができます。検証は、各INSERT文ではなくCOMMITで行われます。
CREATE ASSERTION manager_has_clerk check
(NOT EXISTS
(SELECT 'manager without clerk'
FROM employees m
WHERE m.job_id = 'ST_MAN'
AND NOT EXISTS
(SELECT 'a clerk in same department'
FROM employees c
WHERE c.job_id = 'ST_CLERK'
AND c.department_id = m.department_id)));