55

私はここのような2つのテーブルを持っています:

DROP   TABLE  IF EXISTS schemas.book;
DROP   TABLE  IF EXISTS schemas.category;
DROP   SCHEMA IF EXISTS schemas;
CREATE SCHEMA schemas;

CREATE TABLE schemas.category (
  id          BIGSERIAL PRIMARY KEY,
  name        VARCHAR   NOT NULL,
  UNIQUE(name)
);

CREATE TABLE schemas.book (
  id          BIGSERIAL PRIMARY KEY,
  published   DATE      NOT NULL,
  category_id BIGINT    NOT NULL REFERENCES schemas.category ON DELETE CASCADE ON UPDATE CASCADE,
  author      VARCHAR   NOT NULL,
  name        VARCHAR   NOT NULL,
  UNIQUE(published, author, name),
  FOREIGN KEY(category_id) REFERENCES schemas.category (id)
);

したがって、ロジックは単純です。ユーザーがカテゴリxの下のすべての本を削除した後、xは猫から削除されます。上記の方法を試しましたが、機能しません。テーブルブックをクリーンアップした後、テーブルカテゴリはまだ入力されていますが、何が問題になっていますか?

4

4 に答える 4

100

カスケード削除のある外部キーは、親テーブルのレコードが削除されると、子テーブルの対応するレコードが自動的に削除されることを意味します。これはカスケード削除と呼ばれます。

逆に言えば、これは、子テーブルから削除すると、レコードが親テーブルから削除されるということではありません。

UPDATE 1:

ON DELETE CASCADEオプションは、対応する行が親テーブルで削除されたときに、子テーブルで行を削除するかどうかを指定します。カスケード削除を指定しない場合、データベースサーバーのデフォルトの動作により、他のテーブルがデータを参照している場合、テーブル内のデータを削除できなくなります。

このオプションを指定すると、後で親テーブルの行を削除するときに、データベースサーバーは子テーブルのその行に関連付けられているすべての行(外部キー)も削除します。カスケード削除機能の主な利点は、削除アクションを実行するために必要なSQLステートメントの量を減らすことができることです。

つまり、子テーブルからではなく親テーブルから行を削除するとどうなるかがすべてです。

したがって、ユーザーがCATsテーブルからエントリを削除すると、booksテーブルから行が削除されます。:)

これがお役に立てば幸いです:)

于 2013-01-03T14:58:59.380 に答える
74

PostgreSQLドキュメントからの抜粋

削除の制限とカスケードは、最も一般的な2つのオプションです。[...]CASCADEは、参照されている行が削除されると、それを参照している行も自動的に削除されることを指定します。

つまり、schemas.categoryで参照されcategory_idているの行を削除するとschemas.books、そのような参照行もすべてで削除されON DELETE CASCADEます。

CREATE SCHEMA shire;

CREATE TABLE shire.clans (
    id serial PRIMARY KEY,
    clan varchar
);

CREATE TABLE shire.hobbits (
    id serial PRIMARY KEY,
    hobbit varchar,
    clan_id integer REFERENCES shire.clans (id) ON DELETE CASCADE
);

DELETE FROM氏族はCASCADEによってホビットになりREFERENCESます。

sauron@mordor> psql
sauron=# SELECT * FROM shire.clans;
 id |    clan    
----+------------
  1 | Baggins
  2 | Gamgi
(2 rows)

sauron=# SELECT * FROM shire.hobbits;
 id |  hobbit  | clan_id 
----+----------+---------
  1 | Bilbo    |       1
  2 | Frodo    |       1
  3 | Samwise  |       2
(3 rows)

sauron=# DELETE FROM shire.clans WHERE id = 1 RETURNING *;
 id |  clan   
----+---------
  1 | Baggins
(1 row)

DELETE 1
sauron=# SELECT * FROM shire.hobbits;
 id |  hobbit  | clan_id 
----+----------+---------
  3 | Samwise  |       2
(1 row)

本当に反対のことが必要な場合(データベースによってチェックされます)、トリガーを作成する必要があります!

于 2015-11-19T14:55:13.387 に答える
-4

postgres 9.6での私の謙虚な経験では、カスケード削除は、些細なサイズを超えて大きくなるテーブルでは実際には機能しません。

  • さらに悪いことに、削除カスケードが実行されている間、関連するテーブルがロックされるため、それらのテーブル(および場合によってはデータベース全体)が使用できなくなります。
  • さらに悪いことに、postgresが削除カスケード中に何をしているのかを知るのは難しいです。時間がかかる場合、どのテーブルが遅くなっていますか?おそらくそれはpg_stats情報のどこかにありますか?わかりにくいです。
于 2018-02-07T18:42:41.947 に答える
-20

PostgreSQLフォージングキーDELETE、UPDATE CASCADE

CREATE TABLE apps_user(
  user_id SERIAL PRIMARY KEY,
  username character varying(30),
  userpass character varying(50),
  created_on DATE
);

CREATE TABLE apps_profile(
    pro_id SERIAL PRIMARY KEY,
    user_id INT4 REFERENCES apps_user(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
    firstname VARCHAR(30),
    lastname VARCHAR(50),
    email VARCHAR UNIQUE,
    dob DATE
);
于 2017-07-15T10:50:11.663 に答える