バージョンごとのドキュメント一覧

5.4. 制約 #

<title>Constraints</title>

Data types are a way to limit the kind of data that can be stored in a table. For many applications, however, the constraint they provide is too coarse. For example, a column containing a product price should probably only accept positive values. But there is no standard data type that accepts only positive numbers. Another issue is that you might want to constrain column data with respect to other columns or rows. For example, in a table containing product information, there should be only one row for each product number. データ型は、テーブルに格納するデータの種類を限定するための方法です。 しかし、多くのアプリケーションでは、型が提供する制約では精密さに欠けます。 例えば、製品の価格が入る列には、おそらく正数のみを受け入れるようにする必要があります。 しかし、正数のみを受け入れるという標準のデータ型はありません。 また、他の列や行に関連して列データを制約したい場合もあります。 例えば、製品の情報が入っているテーブルでは、1つの製品番号についての行が2行以上あってはなりません。

To that end, SQL allows you to define constraints on columns and tables. Constraints give you as much control over the data in your tables as you wish. If a user attempts to store data in a column that would violate a constraint, an error is raised. This applies even if the value came from the default value definition. このような問題を解決するため、SQLでは列およびテーブルに対する制約を定義できます。 制約によってテーブル内のデータを自由に制御できます。 制約に違反するデータを列に格納しようとすると、エラーとなります。 このことは、デフォルト値として定義された値を格納する場合にも適用されます。

5.4.1. 検査制約 #

<title>Check Constraints</title>

A check constraint is the most generic constraint type. It allows you to specify that the value in a certain column must satisfy a Boolean (truth-value) expression. For instance, to require positive product prices, you could use: 検査制約は最も汎用的な制約の種類です。 これを使用して、特定の列の値が論理値の式を満たす(真の値)ように指定できます。 例えば、製品価格を必ず正数にするには以下のようにします。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CHECK (price > 0)
);

As you see, the constraint definition comes after the data type, just like default value definitions. Default values and constraints can be listed in any order. A check constraint consists of the key word <literal>CHECK</literal> followed by an expression in parentheses. The check constraint expression should involve the column thus constrained, otherwise the constraint would not make too much sense. このように、制約の定義はデフォルト値の定義と同様に、データ型の後にきます。 デフォルト値と制約は任意の順序で列挙できます。 検査制約はCHECKキーワードの後に続く括弧で囲まれた式で構成されます。 検査制約式には、制約される列を含む必要があります。 そうしないと、制約はあまり意味のないものになります。

You can also give the constraint a separate name. This clarifies error messages and allows you to refer to the constraint when you need to change it. The syntax is: 制約に個別に名前を付けることもできます。 名前を付けることで、エラーメッセージがわかりやすくなりますし、変更したい制約を参照できます。 構文は以下のとおりです。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CONSTRAINT positive_price CHECK (price > 0)
);

So, to specify a named constraint, use the key word <literal>CONSTRAINT</literal> followed by an identifier followed by the constraint definition. (If you don't specify a constraint name in this way, the system chooses a name for you.) 上記のように、名前付き制約の指定はCONSTRAINTキーワードで始め、これに識別子、制約定義と続きます。 (この方法で制約名を指定しない場合は、システムにより名前が付けられます。)

A check constraint can also refer to several columns. Say you store a regular price and a discounted price, and you want to ensure that the discounted price is lower than the regular price: 検査制約では複数の列を参照することもできます。 例えば、通常価格と割引価格を格納する場合に、必ず割引価格が通常価格よりも低くなるようにしたいとします。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CHECK (price > 0),
    discounted_price numeric CHECK (discounted_price > 0),
    CHECK (price > discounted_price)
);

The first two constraints should look familiar. The third one uses a new syntax. It is not attached to a particular column, instead it appears as a separate item in the comma-separated column list. Column definitions and these constraint definitions can be listed in mixed order. 最初の2つの制約は上で説明した通りです。 3つ目の制約では新しい構文を使っています。 これは特定の列に付加されるのではなく、カンマで区切られた列リスト内の別個の項目として現れます。 列定義およびこれらの制約定義は、任意の順序で列挙できます。

We say that the first two constraints are column constraints, whereas the third one is a table constraint because it is written separately from any one column definition. Column constraints can also be written as table constraints, while the reverse is not necessarily possible, since a column constraint is supposed to refer to only the column it is attached to. (<productname>PostgreSQL</productname> doesn't enforce that rule, but you should follow it if you want your table definitions to work with other database systems.) The above example could also be written as: 最初の2つの制約を列制約と言います。これに対し、3つ目の制約は列定義とは別個に書かれるので、テーブル制約と言います。 列制約をテーブル制約として書くことはできますが、その逆はできる場合とできない場合があります。なぜなら列制約は、制約に関連付けられている列のみを参照するためです。 (PostgreSQLはこの規則を強制しません。しかし、作成したテーブル定義を他のデータベースシステムでも動作させたい場合はこの規則に従ってください。) 上の例は、以下のように書くこともできます。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric,
    CHECK (price > 0),
    discounted_price numeric,
    CHECK (discounted_price > 0),
    CHECK (price > discounted_price)
);

or even: あるいは、次のようにもできます。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CHECK (price > 0),
    discounted_price numeric,
    CHECK (discounted_price > 0 AND price > discounted_price)
);

It's a matter of taste. どのようにするかは好みの問題です。

Names can be assigned to table constraints in the same way as column constraints: 列制約と同様に、テーブル制約に名前を割り当てることができます。

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric,
    CHECK (price > 0),
    discounted_price numeric,
    CHECK (discounted_price > 0),
    CONSTRAINT valid_discount CHECK (price > discounted_price)
);

It should be noted that a check constraint is satisfied if the check expression evaluates to true or the null value. Since most expressions will evaluate to the null value if any operand is null, they will not prevent null values in the constrained columns. To ensure that a column does not contain null values, the not-null constraint described in the next section can be used. 検査制約では、検査式が真またはNULL値と評価された場合に、条件が満たされることに注意してください。 ほとんどの式は、演算項目に一つでもNULLがあればNULLと評価されるので、検査制約では制約対象の列にNULL値が入るのを防げません。 列がNULL値を含まないようにするために、次節で説明する非NULL制約を使用できます。

注記

<productname>PostgreSQL</productname> does not support <literal>CHECK</literal> constraints that reference table data other than the new or updated row being checked. While a <literal>CHECK</literal> constraint that violates this rule may appear to work in simple tests, it cannot guarantee that the database will not reach a state in which the constraint condition is false (due to subsequent changes of the other row(s) involved). This would cause a database dump and restore to fail. The restore could fail even when the complete database state is consistent with the constraint, due to rows not being loaded in an order that will satisfy the constraint. If possible, use <literal>UNIQUE</literal>, <literal>EXCLUDE</literal>, or <literal>FOREIGN KEY</literal> constraints to express cross-row and cross-table restrictions. PostgreSQLは、検査対象の新しい行もしくは更新対象行以外のテーブルデータを参照するCHECK制約はサポートしていません。 このルールに違反するCHECK制約は単純なテストでは動いたように見えますが、(関連する他の行が後で更新されたことにより)データベースがその制約条件が偽になるような状態にならないことを保証できません。 これによってデータベースのダンプとリストアの失敗が引き起こされるでしょう。 最終的なデータベース状態が制約に対して一貫した状態であったとしても、制約を満たす順で行がロードされないことによりリストアは失敗することがあります。 可能ならばUNIQUEEXCLUDEFOREIGN KEY制約を使って行あるいはテーブルをまたがる制約を表現してください。

If what you desire is a one-time check against other rows at row insertion, rather than a continuously-maintained consistency guarantee, a custom <link linkend="triggers">trigger</link> can be used to implement that. (This approach avoids the dump/restore problem because <application>pg_dump</application> does not reinstall triggers until after restoring data, so that the check will not be enforced during a dump/restore.) 常に一貫性の保障を維持するのではなく、行挿入の際に一回だけの行の検査が必要なら、その実装のためにカスタムトリガが利用できます。 (pg_dumpはデータのリストア後までトリガを再インストールせず、ダンプ/リストア中は検査が強制されないため、この方法でダンプ/リストア問題を回避できます。)

注記

<productname>PostgreSQL</productname> assumes that <literal>CHECK</literal> constraints' conditions are immutable, that is, they will always give the same result for the same input row. This assumption is what justifies examining <literal>CHECK</literal> constraints only when rows are inserted or updated, and not at other times. (The warning above about not referencing other table data is really a special case of this restriction.) PostgreSQLCHECK制約の条件が不変であると仮定します。 つまり同じ入力行に対して常に同じ結果が返るということです。 この仮定によりCHECK制約が挿入あるいは更新時にのみ検査され、他のときには検査されないことが正当化されます。 (他のテーブルデータを参照しないことによる上述の警告はこの制限の本当に特別な場合です。)

An example of a common way to break this assumption is to reference a user-defined function in a <literal>CHECK</literal> expression, and then change the behavior of that function. <productname>PostgreSQL</productname> does not disallow that, but it will not notice if there are rows in the table that now violate the <literal>CHECK</literal> constraint. That would cause a subsequent database dump and restore to fail. The recommended way to handle such a change is to drop the constraint (using <command>ALTER TABLE</command>), adjust the function definition, and re-add the constraint, thereby rechecking it against all table rows. この仮定に反する一般的な例は、CHECK式でユーザ定義関数を参照し、その関数の振る舞いを変更することです。 PostgreSQLはこれを禁止しませんが、今やCHECK制約に違反する行がテーブル中に存在することを通知しません。 これによって後でデータベースのダンプとリストアの失敗を引き起こすでしょう。 そのような変更に対処するおすすめの方法は、(ALTER TABLEを使って)制約を削除し、関数定義を調整し、そして制約を再度追加して、それによってテーブル全体の行に対して再チェックを行うことです。

5.4.2. 非NULL制約 #

<title>Not-Null Constraints</title>

A not-null constraint simply specifies that a column must not assume the null value. A syntax example: 非NULL制約は単純に、列がNULL値を取らないことを指定します。 構文の例は以下のとおりです。

CREATE TABLE products (
    product_no integer NOT NULL,
    name text NOT NULL,
    price numeric
);

A not-null constraint is always written as a column constraint. A not-null constraint is functionally equivalent to creating a check constraint <literal>CHECK (<replaceable>column_name</replaceable> IS NOT NULL)</literal>, but in <productname>PostgreSQL</productname> creating an explicit not-null constraint is more efficient. The drawback is that you cannot give explicit names to not-null constraints created this way. 非NULL制約は常に列制約として記述されます。 非NULL制約はCHECK (column_name IS NOT NULL)という検査制約と機能的には同等ですが、PostgreSQLでは、明示的に非NULL制約を作成する方がより効果的です。 このように作成された非NULL制約に明示的な名前を付けられないのが欠点です。

Of course, a column can have more than one constraint. Just write the constraints one after another: もちろん、1つの列に複数の制約を適用することもできます。 そのためには、次々と制約を書いていくだけです。

CREATE TABLE products (
    product_no integer NOT NULL,
    name text NOT NULL,
    price numeric NOT NULL CHECK (price > 0)
);

The order doesn't matter. It does not necessarily determine in which order the constraints are checked. 順序は関係ありません。 書かれた順序と検査される順序は必ずしも同じではありません。

The <literal>NOT NULL</literal> constraint has an inverse: the <literal>NULL</literal> constraint. This does not mean that the column must be null, which would surely be useless. Instead, this simply selects the default behavior that the column might be null. The <literal>NULL</literal> constraint is not present in the SQL standard and should not be used in portable applications. (It was only added to <productname>PostgreSQL</productname> to be compatible with some other database systems.) Some users, however, like it because it makes it easy to toggle the constraint in a script file. For example, you could start with: NOT NULL制約に対し、逆のパターンであるNULL制約があります。 これは、列がNULLでなければならないということではありません。 そのような制約は意味がありません。 この制約は、列がNULLであってもよいというデフォルトの振舞いを選択するだけのものです。 NULL制約は標準SQLに存在しませんので、移植予定のアプリケーションで使用すべきではありません。 (これは、PostgreSQLと他の一部のデータベースシステムとの互換性のために追加された機能に過ぎません。) もっとも、スクリプトファイルでの制約の切り替えが簡単であるという理由でこの機能を歓迎するユーザもいます。 例えば、最初に

CREATE TABLE products (
    product_no integer NULL,
    name text NULL,
    price numeric NULL
);

and then insert the <literal>NOT</literal> key word where desired. と書いてから、必要な場所にNOTキーワードを挿入できます。

ヒント

In most database designs the majority of columns should be marked not null. ほとんどのデータベース設計において、列の多くをNOT NULLとマークする必要があります。

5.4.3. 一意性制約 #

<title>Unique Constraints</title>

Unique constraints ensure that the data contained in a column, or a group of columns, is unique among all the rows in the table. The syntax is: 一意性制約によって、列あるいは列のグループに含まれるデータが、テーブル内の全ての行で一意であることを確実にします。 列制約の場合の構文は以下のとおりです。

CREATE TABLE products (
    product_no integer UNIQUE,
    name text,
    price numeric
);

when written as a column constraint, and: また、テーブル制約の場合の構文は

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric,
    UNIQUE (product_no)
);

when written as a table constraint. となります。

To define a unique constraint for a group of columns, write it as a table constraint with the column names separated by commas: 列の集合に対して一意性制約を定義するには、列名をカンマで区切り、テーブル制約として記述します。

CREATE TABLE example (
    a integer,
    b integer,
    c integer,
    UNIQUE (a, c)
);

This specifies that the combination of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique. これは、指定された列の値の組み合わせがテーブル全体で一意であることを指定しています。 しかし、列の片方が一意である必要はありません(通常一意ではありません)。

You can assign your own name for a unique constraint, in the usual way: 一意性制約には、通常の方法で名前を割り当てることもできます。

CREATE TABLE products (
    product_no integer CONSTRAINT must_be_different UNIQUE,
    name text,
    price numeric
);

Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique <link linkend="indexes-partial">partial index</link>. 一意性制約を追加すると、制約で指定された列または列のグループに対して一意的なBツリーのインデックスが自動的に作られます。 一部の行だけに適用される一意性の制限を一意性制約として作成することはできませんが、そのような制限を一意な部分インデックスを作成することで実現することは可能です。

In general, a unique constraint is violated if there is more than one row in the table where the values of all of the columns included in the constraint are equal. By default, two null values are not considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior can be changed by adding the clause <literal>NULLS NOT DISTINCT</literal>, like 一般的には、制約に含まれるすべての列の値が等しい複数の行がテーブルの中にある場合に、一意性制約に違反します。 この比較において、デフォルトでは2つのNULL値は等しくないとみなされます。 つまり、一意性制約が存在する場合でも、制約が適用される列の少なくとも1つにNULL値を含むような重複行が格納できるということです。 この動作は、次のようにNULLS NOT DISTINCT句を追加することで変更できます。

CREATE TABLE products (
    product_no integer UNIQUE NULLS NOT DISTINCT,
    name text,
    price numeric
);

or または

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric,
    UNIQUE NULLS NOT DISTINCT (product_no)
);

The default behavior can be specified explicitly using <literal>NULLS DISTINCT</literal>. The default null treatment in unique constraints is implementation-defined according to the SQL standard, and other implementations have a different behavior. So be careful when developing applications that are intended to be portable. デフォルトの動作は、NULLS DISTINCTを使用して明示的に指定できます。 標準SQLによれば、一意性制約でのデフォルトのNULL処理は実装依存で、他の実装では動作が異なります。 そのため、移植可能なアプリケーションを開発する際には注意が必要です。

5.4.4. 主キー #

<title>Primary Keys</title>

A primary key constraint indicates that a column, or group of columns, can be used as a unique identifier for rows in the table. This requires that the values be both unique and not null. So, the following two table definitions accept the same data: 主キー制約は、列または列のグループがテーブル内の行を一意に識別するものとして利用できることを意味します。 これには値が一意で、かつNULLでないことが必要となります。 つまり、次の2つのテーブル定義は同じデータを受け入れます。

CREATE TABLE products (
    product_no integer UNIQUE NOT NULL,
    name text,
    price numeric
);

CREATE TABLE products (
    product_no integer PRIMARY KEY,
    name text,
    price numeric
);

Primary keys can span more than one column; the syntax is similar to unique constraints: 主キーも複数の列に渡ることがあり、その構文は一意性制約に似ています。

CREATE TABLE example (
    a integer,
    b integer,
    c integer,
    PRIMARY KEY (a, c)
);

Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked <literal>NOT NULL</literal>. 主キーを追加すると、主キーで指定された列または列のグループに対して一意的なBツリーのインデックスが自動的に作られます。 また、その列についてNOT NULLの印が強制されます。

A table can have at most one primary key. (There can be any number of unique and not-null constraints, which are functionally almost the same thing, but only one can be identified as the primary key.) Relational database theory dictates that every table must have a primary key. This rule is not enforced by <productname>PostgreSQL</productname>, but it is usually best to follow it. 1つのテーブルは最大1つの主キーを持つことができます。 (一意性制約および非NULL制約に個数の制限はありません。 機能的にはほとんど同じものですが、主キーとして識別される制約は1つのみです。) リレーショナルデータベース理論では、全てのテーブルに主キーが1つ必要とされています。 この規則はPostgreSQLでは強制されませんが、たいていの場合はこれに従うことが推奨されます。

Primary keys are useful both for documentation purposes and for client applications. For example, a GUI application that allows modifying row values probably needs to know the primary key of a table to be able to identify rows uniquely. There are also various ways in which the database system makes use of a primary key if one has been declared; for example, the primary key defines the default target column(s) for foreign keys referencing its table. 主キーは文書化、および、クライアントアプリケーションの両方の面で役に立ちます。 例えば、行値の変更が可能なGUIアプリケーションが行を一意的に特定するためには、 おそらくテーブルの主キーを知る必要があります。 他にも主キーが宣言されているときにデータベースシステムがそれを利用する場面がいくつかあります。 例えば、外部キーがそのテーブルを参照するとき、主キーがデフォルトの対象列となります。

5.4.5. 外部キー #

<title>Foreign Keys</title>

A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row of another table. We say this maintains the <firstterm>referential integrity</firstterm> between two related tables. 外部キー制約は、列(または列のグループ)の値が、他のテーブルの行の値と一致しなければならないことを指定します。 これによって関連する2つのテーブルの参照整合性が維持されます。

Say you have the product table that we have used several times already: これまで何度か例に使用したproductsテーブルについて考えてみます。

CREATE TABLE products (
    product_no integer PRIMARY KEY,
    name text,
    price numeric
);

Let's also assume you have a table storing orders of those products. We want to ensure that the orders table only contains orders of products that actually exist. So we define a foreign key constraint in the orders table that references the products table: また、これらの製品に対する注文を格納するテーブルも作成済みだとしましょう。 この注文のordersテーブルには実際に存在する製品の注文のみを格納したいと思っています。 そこで、productsテーブルを参照するordersテーブルに外部キー制約を定義します。

CREATE TABLE orders (
    order_id integer PRIMARY KEY,
    product_no integer REFERENCES products (product_no),
    quantity integer
);

Now it is impossible to create orders with non-NULL <structfield>product_no</structfield> entries that do not appear in the products table. これで、productsテーブルに存在しない非NULLのproduct_no項目を使用して注文を作成することはできなくなります。

We say that in this situation the orders table is the <firstterm>referencing</firstterm> table and the products table is the <firstterm>referenced</firstterm> table. Similarly, there are referencing and referenced columns. このような場合に、ordersテーブルのことを参照テーブル、productテーブルのことを被参照テーブルと呼びます。 同様に、参照列と被参照列もあります。

You can also shorten the above command to: 上記のコマンドは、次のように短縮することもできます。

CREATE TABLE orders (
    order_id integer PRIMARY KEY,
    product_no integer REFERENCES products,
    quantity integer
);

because in absence of a column list the primary key of the referenced table is used as the referenced column(s). 列リストがないため、被参照テーブルの主キーが被参照列として使用されます。

You can assign your own name for a foreign key constraint, in the usual way. 外部キー制約には、通常の方法で名前を割り当てることもできます。

A foreign key can also constrain and reference a group of columns. As usual, it then needs to be written in table constraint form. Here is a contrived syntax example: 外部キーでも、列のグループを制約したり参照したりすることもできます。 これもまた、テーブル制約の形式で記述する必要があります。 以下は、説明のための非現実的な例です。

CREATE TABLE t1 (
  a integer PRIMARY KEY,
  b integer,
  c integer,
  FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)
);

Of course, the number and type of the constrained columns need to match the number and type of the referenced columns. もちろん、制約される列数および型は、被参照列の数および型と一致しなければなりません。

Sometimes it is useful for the <quote>other table</quote> of a foreign key constraint to be the same table; this is called a <firstterm>self-referential</firstterm> foreign key. For example, if you want rows of a table to represent nodes of a tree structure, you could write 時には外部キー制約の他のテーブルを同じテーブルにすることが有用です。 これは自己参照外部キーと呼ばれます。 たとえばテーブルの行がツリー構造のノードを表現するようにしたいのであれば、以下のように書くことができるでしょう。

CREATE TABLE tree (
    node_id integer PRIMARY KEY,
    parent_id integer REFERENCES tree,
    name text,
    ...
);

A top-level node would have NULL <structfield>parent_id</structfield>, while non-NULL <structfield>parent_id</structfield> entries would be constrained to reference valid rows of the table. トップレベルのノードはparent_idがNULLなのに対し、非NULLのparent_idはテーブルの有効な行を参照するように制約されることになります。

A table can have more than one foreign key constraint. This is used to implement many-to-many relationships between tables. Say you have tables about products and orders, but now you want to allow one order to contain possibly many products (which the structure above did not allow). You could use this table structure: テーブルは複数の外部キー制約を持つことができます。 このことはテーブル間の多対多関係を実装するために使用されます。 例えば、製品と注文に関するそれぞれのテーブルがある場合に、複数の製品にまたがる注文を可能にしたいとします (上の例の構造では不可能です)。 この場合、次のテーブル構造を使用できます。

CREATE TABLE products (
    product_no integer PRIMARY KEY,
    name text,
    price numeric
);

CREATE TABLE orders (
    order_id integer PRIMARY KEY,
    shipping_address text,
    ...
);

CREATE TABLE order_items (
    product_no integer REFERENCES products,
    order_id integer REFERENCES orders,
    quantity integer,
    PRIMARY KEY (product_no, order_id)
);

Notice that the primary key overlaps with the foreign keys in the last table. 最後のテーブルで、主キーと外部キーが重なっていることに注目してください。

We know that the foreign keys disallow creation of orders that do not relate to any products. But what if a product is removed after an order is created that references it? SQL allows you to handle that as well. Intuitively, we have a few options: 外部キーが製品に関連付けられていない注文の作成を許可しないことは、既に説明した通りです。 しかし、ある注文で参照していた製品が、注文後に削除されたらどうなるでしょう。 SQLではこのような場合も扱うことができます。 直感的に、いくつかのオプションが考えられます。

<listitem><para>Disallow deleting a referenced product</para></listitem> <listitem><para>Delete the orders as well</para></listitem> <listitem><para>Something else?</para></listitem>
  • 参照される製品の削除を許可しない

  • 注文も一緒に削除する

  • 他にもありますか?

To illustrate this, let's implement the following policy on the many-to-many relationship example above: when someone wants to remove a product that is still referenced by an order (via <literal>order_items</literal>), we disallow it. If someone removes an order, the order items are removed as well: 具体例として、上の例の多対多関係に次のポリシーを実装してみましょう。 (order_itemsによって)注文で参照されたままの製品を削除しようとしても、この操作を行えないようにします。 注文が削除されると、注文項目も削除されます。

CREATE TABLE products (
    product_no integer PRIMARY KEY,
    name text,
    price numeric
);

CREATE TABLE orders (
    order_id integer PRIMARY KEY,
    shipping_address text,
    ...
);

CREATE TABLE order_items (
    product_no integer REFERENCES products ON DELETE RESTRICT,
    order_id integer REFERENCES orders ON DELETE CASCADE,
    quantity integer,
    PRIMARY KEY (product_no, order_id)
);

Restricting and cascading deletes are the two most common options. <literal>RESTRICT</literal> prevents deletion of a referenced row. <literal>NO ACTION</literal> means that if any referencing rows still exist when the constraint is checked, an error is raised; this is the default behavior if you do not specify anything. (The essential difference between these two choices is that <literal>NO ACTION</literal> allows the check to be deferred until later in the transaction, whereas <literal>RESTRICT</literal> does not.) <literal>CASCADE</literal> specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. There are two other options: <literal>SET NULL</literal> and <literal>SET DEFAULT</literal>. These cause the referencing column(s) in the referencing row(s) to be set to nulls or their default values, respectively, when the referenced row is deleted. Note that these do not excuse you from observing any constraints. For example, if an action specifies <literal>SET DEFAULT</literal> but the default value would not satisfy the foreign key constraint, the operation will fail. 削除の制限およびカスケードという2つは、最も一般的なオプションです。 RESTRICTは、被参照行が削除されるのを防ぎます。 NO ACTIONは、制約が検査された時に参照行がまだ存在していた場合に、エラーとなることを意味しています。 これは、何も指定しない場合のデフォルトの振舞いとなります (これらの本質的な違いは、NO ACTIONでは検査をトランザクション中で後回しにできるのに対し、RESTRICTでは後回しにできないということです)。 CASCADEは被参照行が削除された時、それを参照する行も同様に削除されることを指定します。 他にも2つのオプション、SET NULLSET DEFAULTがあります。 これらは、被参照行が削除された際に、参照行の参照列がそれぞれNULLか各列のデフォルト値に設定されます。 これらは制約を守ることを免除することではない、ということに注意してください。 例えば、動作にSET DEFAULTを指定したとしても、デフォルト値が外部キー制約を満たさない場合には操作は失敗します。

The appropriate choice of <literal>ON DELETE</literal> action depends on what kinds of objects the related tables represent. When the referencing table represents something that is a component of what is represented by the referenced table and cannot exist independently, then <literal>CASCADE</literal> could be appropriate. If the two tables represent independent objects, then <literal>RESTRICT</literal> or <literal>NO ACTION</literal> is more appropriate; an application that actually wants to delete both objects would then have to be explicit about this and run two delete commands. In the above example, order items are part of an order, and it is convenient if they are deleted automatically if an order is deleted. But products and orders are different things, and so making a deletion of a product automatically cause the deletion of some order items could be considered problematic. The actions <literal>SET NULL</literal> or <literal>SET DEFAULT</literal> can be appropriate if a foreign-key relationship represents optional information. For example, if the products table contained a reference to a product manager, and the product manager entry gets deleted, then setting the product's product manager to null or a default might be useful. ON DELETEアクションの適切な選択は、関連するテーブルが表すオブジェクトの種類によって異なります。 参照元テーブルが、参照先テーブルによって表されるオブジェクトのコンポーネントであり、独立して存在できないものを表している場合は、CASCADEが適切です。 2つのテーブルが独立したオブジェクトを表している場合は、RESTRICTまたはNO ACTIONが適切です。 実際に両方のオブジェクトを削除するアプリケーションは、このことを明示的に指定し、2つの削除コマンドを実行する必要があります。 前述の例では、受注アイテムは受注の一部であり、受注が削除された場合に自動的に削除されるようにすると便利です。 ただし、製品と受注は異なるため、製品を削除すると一部の受注アイテムが自動的に削除されてしまうのは問題となると考えられます。 外部キー関係がオプションの情報を表す場合は、アクションSET NULLまたはSET DEFAULTが適切です。 たとえば、製品テーブルに製品マネージャへの参照が含まれていて、製品マネージャのエントリが削除された場合、製品の製品マネージャをNULLまたはデフォルトに設定すると便利です。

The actions <literal>SET NULL</literal> and <literal>SET DEFAULT</literal> can take a column list to specify which columns to set. Normally, all columns of the foreign-key constraint are set; setting only a subset is useful in some special cases. Consider the following example: アクションSET NULLおよびSET DEFAULTでは、列リストを使用して、設定する列を指定できます。 通常、外部キー制約のすべての列が設定されます。 サブセットのみを設定すると、特殊な場合に役立ちます。次の例を見てください。

CREATE TABLE tenants (
    tenant_id integer PRIMARY KEY
);

CREATE TABLE users (
    tenant_id integer REFERENCES tenants ON DELETE CASCADE,
    user_id integer NOT NULL,
    PRIMARY KEY (tenant_id, user_id)
);

CREATE TABLE posts (
    tenant_id integer REFERENCES tenants ON DELETE CASCADE,
    post_id integer NOT NULL,
    author_id integer,
    PRIMARY KEY (tenant_id, post_id),
    FOREIGN KEY (tenant_id, author_id) REFERENCES users ON DELETE SET NULL (author_id)
);

Without the specification of the column, the foreign key would also set the column <literal>tenant_id</literal> to null, but that column is still required as part of the primary key. 列が指定されていない場合、外部キーもtenant_id列をnullに設定しますが、この列は主キーの一部として必要です。

Analogous to <literal>ON DELETE</literal> there is also <literal>ON UPDATE</literal> which is invoked when a referenced column is changed (updated). The possible actions are the same, except that column lists cannot be specified for <literal>SET NULL</literal> and <literal>SET DEFAULT</literal>. In this case, <literal>CASCADE</literal> means that the updated values of the referenced column(s) should be copied into the referencing row(s). ON DELETEについても同様で、被参照列が変更(更新)された時に呼び出されるON UPDATEもあります。 列リストがSET NULLSET DEFAULTで指定できない点を除き、可能なアクションは同じです。 この場合、CASCADEは被参照列の更新後の値が参照行にコピーされることを意味します。

Normally, a referencing row need not satisfy the foreign key constraint if any of its referencing columns are null. If <literal>MATCH FULL</literal> is added to the foreign key declaration, a referencing row escapes satisfying the constraint only if all its referencing columns are null (so a mix of null and non-null values is guaranteed to fail a <literal>MATCH FULL</literal> constraint). If you don't want referencing rows to be able to avoid satisfying the foreign key constraint, declare the referencing column(s) as <literal>NOT NULL</literal>. 通常、参照行はその参照列のいずれかがnullの場合は外部キー制約を満たす必要がありません。 もしMATCH FULLが外部キー宣言に追加された場合、その参照列の全てがnullの場合にのみ参照行は制約を満たすことから逃れることができます(つまりnullと非nullの組み合わせはMATCH FULL制約に違反することが保証されます)。 もし参照行が外部キー制約を満たさない可能性を排除したい場合は、参照列をNOT NULLとして宣言してください。

A foreign key must reference columns that either are a primary key or form a unique constraint. This means that the referenced columns always have an index (the one underlying the primary key or unique constraint); so checks on whether a referencing row has a match will be efficient. Since a <command>DELETE</command> of a row from the referenced table or an <command>UPDATE</command> of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, declaration of a foreign key constraint does not automatically create an index on the referencing columns. 外部キーは主キーであるかまたは一意性制約を構成する列を参照しなければなりません。 これは、被参照列は常に(主キーまたは一意性制約の基礎となる)インデックスを持つことを意味します。 このため、参照行に一致する行があるかどうかのチェックは効率的です。 被参照テーブルからの行のDELETEや被参照行のUPDATEは、古い値と一致する行に対して参照テーブルのスキャンが必要となるので、参照行にもインデックスを付けるのは大抵は良い考えです。 これは常に必要という訳ではなく、また、インデックスの方法には多くの選択肢がありますので、外部キー制約の宣言では参照列のインデックスが自動的に作られるということはありません。

More information about updating and deleting data is in <xref linkend="dml"/>. Also see the description of foreign key constraint syntax in the reference documentation for <xref linkend="sql-createtable"/>. データの更新および削除について詳しくは、第6章を参照してください。 また、CREATE TABLEのリファレンス文書にある外部キー制約構文の説明も参照してください。

5.4.6. 排他制約 #

<title>Exclusion Constraints</title>

Exclusion constraints ensure that if any two rows are compared on the specified columns or expressions using the specified operators, at least one of these operator comparisons will return false or null. The syntax is: 排他制約によって、2つの行に関して指定された列もしくは式を指定された演算子を利用して比較した場合に、少なくとも演算子の比較の1つが偽もしくはnullを返すことを確実にします。 構文は以下のとおりです。

CREATE TABLE circles (
    c circle,
    EXCLUDE USING gist (c WITH &&)
);

See also <link linkend="sql-createtable-exclude"><command>CREATE TABLE ... CONSTRAINT ... EXCLUDE</command></link> for details. 詳細はCREATE TABLE ... CONSTRAINT ... EXCLUDEを参照してください。

Adding an exclusion constraint will automatically create an index of the type specified in the constraint declaration. 排他制約を追加すると、制約宣言で指定された種類のインデックスが自動的に作られます。