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

5.14. 依存関係の追跡 #

<title>Dependency Tracking</title>

When you create complex database structures involving many tables with foreign key constraints, views, triggers, functions, etc. you implicitly create a net of dependencies between the objects. For instance, a table with a foreign key constraint depends on the table it references. 外部キー制約や、ビュー、トリガ、関数などを使ったテーブルが多数含まれるような複雑なデータベース構造を作成すると、ユーザはそれらのオブジェクト間の暗黙的な依存関係のネットワークも作成していることになります。 例えば、外部キー制約を持つテーブルは、参照するテーブルに依存しています。

To ensure the integrity of the entire database structure, <productname>PostgreSQL</productname> makes sure that you cannot drop objects that other objects still depend on. For example, attempting to drop the products table we considered in <xref linkend="ddl-constraints-fk"/>, with the orders table depending on it, would result in an error message like this: データベース構造全体の整合性を保つため、PostgreSQLは、他のオブジェクトと依存関係にあるオブジェクトの削除を許可しません。 例えば、5.4.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.

The error message contains a useful hint: if you do not want to bother deleting all the dependent objects individually, you can run: エラーメッセージには役に立つヒントが含まれています。 以下のようにすると、依存する全てのオブジェクトを1つずつ削除する手間を省けます。

DROP TABLE products CASCADE;

and all the dependent objects will be removed, as will any objects that depend on them, recursively. In this case, it doesn't remove the orders table, it only removes the foreign key constraint. It stops there because nothing depends on the foreign key constraint. (If you want to check what <command>DROP ... CASCADE</command> will do, run <command>DROP</command> without <literal>CASCADE</literal> and read the <literal>DETAIL</literal> output.) これで、全ての依存オブジェクトが削除され、それらに依存するいかなるオブジェクトも削除されます。 この場合、ordersテーブルは削除されずに外部キー制約のみが削除されます。 外部キー制約に依存するものが何もないので、処理がそこで停止します。 (DROP ... CASCADEが何を行うかを知りたい場合は、CASCADEを指定せずにDROPを実行してDETAIL出力を読んでください)。

Almost all <command>DROP</command> commands in <productname>PostgreSQL</productname> support specifying <literal>CASCADE</literal>. Of course, the nature of the possible dependencies varies with the type of the object. You can also write <literal>RESTRICT</literal> instead of <literal>CASCADE</literal> to get the default behavior, which is to prevent dropping objects that any other objects depend on. PostgreSQLでは、ほぼ全てのDROPコマンドにCASCADEを指定できます。 もちろん、どのような依存関係が存在するかは、オブジェクトの種類によって異なります。 また、CASCADEではなくRESTRICTと記述することもできます。 これは、他のオブジェクトが依存しているオブジェクトの削除を禁止するというデフォルトの振舞いになります。

注記

According to the SQL standard, specifying either <literal>RESTRICT</literal> or <literal>CASCADE</literal> is required in a <command>DROP</command> command. No database system actually enforces that rule, but whether the default behavior is <literal>RESTRICT</literal> or <literal>CASCADE</literal> varies across systems. 標準SQLでは、DROPコマンドでRESTRICTまたはCASCADEのいずれかを指定する必要があります。 実際にこの決まり通りのデータベースシステムはありませんが、デフォルトがRESTRICTであるか、CASCADEであるかは、システムによって異なります。

If a <command>DROP</command> command lists multiple objects, <literal>CASCADE</literal> is only required when there are dependencies outside the specified group. For example, when saying <literal>DROP TABLE tab1, tab2</literal> the existence of a foreign key referencing <literal>tab1</literal> from <literal>tab2</literal> would not mean that <literal>CASCADE</literal> is needed to succeed. DROPコマンドで複数のオブジェクトを羅列した場合、CASCADEは、指定されたグループの外部に依存関係が存在する時のみ要求されます。 例えば、DROP TABLE tab1, tab2と記述したとき、tab2からtab1への外部キー参照の存在は、CASCADEの指定がコマンド成功に必要とされるということを意味しません。

For a user-defined function or procedure whose body is defined as a string literal, <productname>PostgreSQL</productname> tracks dependencies associated with the function's externally-visible properties, such as its argument and result types, but <emphasis>not</emphasis> dependencies that could only be known by examining the function body. As an example, consider this situation: ユーザ定義の関数またはプロシージャでは、本体が文字列リテラルとして定義されている場合、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;

(See <xref linkend="xfunc-sql"/> for an explanation of SQL-language functions.) <productname>PostgreSQL</productname> will be aware that the <function>get_color_note</function> function depends on the <type>rainbow</type> type: dropping the type would force dropping the function, because its argument type would no longer be defined. But <productname>PostgreSQL</productname> will not consider <function>get_color_note</function> to depend on the <structname>my_colors</structname> table, and so will not drop the function if the table is dropped. While there are disadvantages to this approach, there are also benefits. The function is still valid in some sense if the table is missing, though executing it would cause an error; creating a new table of the same name would allow the function to work again. (SQL言語による関数についての説明は38.5を参照してください。) PostgreSQLは関数get_color_noteが型rainbowに依存することは認識します。 例えば、その型を削除すると、関数の引数の型が定義されなくなるため、関数の削除も強制されます。 しかし、PostgreSQLget_color_noteがテーブルmy_colorsに依存するとは考えません。 従って、そのテーブルが削除されても関数は削除されません。 この方法には不利な点もありますが、同時に利益もあります。 テーブルがない状態で関数を実行すればエラーを引き起こしますが、それでも関数はある意味で、有効な状態になっています。 そのため、同じ名前の新しいテーブルを作成することで、関数を再び動作させることができます。

On the other hand, for a SQL-language function or procedure whose body is written in SQL-standard style, the body is parsed at function definition time and all dependencies recognized by the parser are stored. Thus, if we write the function above as 一方、SQL言語で記述されている関数またはプロシージャでは、本体が標準SQLスタイルで記述されている場合、本体は関数定義時に解析され、パーサによって認識された全ての依存関係が格納されます。 したがって、上記の関数を以下のように記述すると

CREATE FUNCTION get_color_note (rainbow) RETURNS text
BEGIN ATOMIC
  SELECT note FROM my_colors WHERE color = $1;
END;

then the function's dependency on the <structname>my_colors</structname> table will be known and enforced by <command>DROP</command>. 関数のmy_colorsテーブルへの依存関係がDROPによって認識され、強制されます。