他のバージョンの文書11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

5.13. 依存関係の追跡

外部キー制約や、ビュー、トリガ、関数などを使ったテーブルが多数含まれるような複雑なデータベース構造を作成すると、ユーザはそれらのオブジェクト間の暗黙的な依存関係のネットワークも作成していることになります。 例えば、外部キー制約を持つテーブルは、参照するテーブルに依存しています。

データベース構造全体の整合性を保つため、PostgreSQLは、他のオブジェクトと依存関係にあるオブジェクトの削除を許可しません。 例えば、5.3.5で検討したproductsテーブルを削除しようとしても、ordersテーブルがこのテーブルに依存しているので、以下のようなエラーメッセージが現れます。

DROP TABLE products;

ERROR:  cannot drop table products because other objects depend on it
DETAIL:  constraint orders_product_no_fkey on table orders depends on table products
HINT:  Use DROP ... CASCADE to drop the dependent objects too.

エラーメッセージには役に立つヒントが含まれています。 以下のようにすると、依存する全てのオブジェクトを1つずつ削除する手間を省けます。

DROP TABLE products CASCADE;

これで、全ての依存オブジェクトが削除され、それらに依存するいかなるオブジェクトも削除されます。 この場合、ordersテーブルは削除されずに外部キー制約のみが削除されます。 外部キー制約に依存するものが何もないので、処理がそこで停止します。 (DROP ... CASCADEが何を行うかを知りたい場合は、CASCADEを指定せずにDROPを実行してDETAIL出力を読んでください)。

PostgreSQLでは、ほぼ全てのDROPコマンドにCASCADEを指定することができます。 もちろん、どのような依存関係が存在するかは、オブジェクトの種類によって異なります。 また、CASCADEではなくRESTRICTと記述することもできます。 これは、他のオブジェクトが依存しているオブジェクトの削除を禁止するというデフォルトの振舞いになります。

注記

標準SQLでは、DROPコマンドでRESTRICTまたはCASCADEのいずれかを指定する必要があります。 実際にこの決まり通りのデータベースシステムはありませんが、デフォルトがRESTRICTであるか、CASCADEであるかは、システムによって異なります。

DROPコマンドで複数のオブジェクトを羅列した場合、CASCADEは、指定されたグループの外部に依存関係が存在する時のみ要求されます。 例えば、DROP TABLE tab1, tab2と記述したとき、tab2からtab1への外部キー参照の存在は、CASCADEの指定がコマンド成功に必要とされるということを意味しません。

ユーザ定義関数について、PostgreSQLは引数や結果の型など、関数の外部に可視な属性に関連した依存性については追跡しますが、関数の実体を検査することによってしかわからない依存性は追跡しません。 例えば以下の状況を考えてみます。

CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow',
                             'green', 'blue', 'purple');

CREATE TABLE my_colors (color rainbow, note text);

CREATE FUNCTION get_color_note (rainbow) RETURNS text AS
  'SELECT note FROM my_colors WHERE color = $1'
  LANGUAGE SQL;

(SQL言語による関数についての説明は38.5を参照してください。) PostgreSQLは関数get_color_noteが型rainbowに依存することは認識します。 例えば、その型を削除すると、関数の引数の型が定義されなくなるため、関数の削除も強制されます。 しかし、PostgreSQLget_color_noteがテーブルmy_colorsに依存するとは考えません。 従って、そのテーブルが削除されても関数は削除されません。 この方法には不利な点もありますが、同時に利益もあります。 テーブルがない状態で関数を実行すればエラーを引き起こしますが、それでも関数はある意味で、有効な状態になっています。 そのため、同じ名前の新しいテーブルを作成することで、関数を再び動作させることができます。