web-dev-qa-db-ja.com

Postgresqlは複数のテーブルから複数の行を削除します

2つ以上のテーブルについて考えます。

users (id, firstname, lastname)
orders (orderid, userid, orderdate, total)

名「Sam」に一致するすべてのsersとそのordersを削除したいと思います。 mysqlでは、通常、左結合を行います。この例では、ユーザーIDは不明です。

クエリの正しい形式は何ですか?

9
fawzib

http://www.postgresql.org/docs/current/static/sql-delete.html

DELETE 
FROM orders o
USING users u
WHERE o.userid = u.id
  and u.firstname = 'Sam';

DELETE 
FROM users u
WHERE u.firstname = 'Sam';

ON delete cascadeを使用してテーブルを作成することもできます

http://www.postgresql.org/docs/current/static/ddl-constraints.html

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)
);
10

適切なカスケード削除を配置することは賢明であり、通常これに対する正しい解決策です。特定の特殊なケースでは、これに関連する別の解決策があります。

共通のデータセットに基づいて複数の削除を実行する必要がある場合は、CTEを使用できます

この主な使用例はカスケード削除でカバーできるため、簡単な例を思い付くのは困難です。

例では、テーブルBから削除する値のセットに値が含まれているテーブルAのすべてのアイテムを削除します。通常、これらはキーですが、そうでない場合、カスケード削除は使用できません。 。

これを解決するには、CTEを使用します

WITH Bdeletes AS (
    DELETE from B where IsSomethingToDelete = true returning ValueThatRelatesToA
)
delete from A where RelatedValue in (select ValueThatRelatesToA from Bdeletes)

この例は、キーマッピングなどについて論じることではなく、共有データセットから2つ以上の削除を実行する方法を示すため、意図的に単純になっています。これは、更新コマンドなども含めて、はるかに複雑になる可能性があります。

これは、より複雑な例です(Darth Vaderの個人データベースから)。この場合、アドレステーブルを参照するテーブルがあります。彼が破壊した惑星のリストにある場合は、アドレステーブルからアドレスを削除する必要があります。この情報を使用して、peopleテーブルから削除しますが、それらが惑星上(または彼のトロフィーキルリスト)にある場合のみです。

with AddressesToDelete as (
    select AddressId from Addresses a 
    join PlanetsDestroyed pd on pd.PlanetName = a.PlanetName
),
PeopleDeleted as (
    delete from People 
    where AddressId in (select * from AddressesToDelete)
    and OffPlanet = false 
    and TrophyKill = false
    returning Id
),
PeopleMissed as (
    update People 
    set AddressId=null, dead=(OffPlanet=false)
    where AddressId in (select * from AddressesToDelete)
    returning id
)
Delete from Addresses where AddressId in (select * from AddressesToDelete)

現在、彼のデータベースは最新です。アドレスの削除による整合性の失敗はありません。更新と最初の削除からデータを返していますが、それを使用する必要があるわけではありません。返されたデータなしでCTEに削除を置くことができるかどうかはわかりません(My SQLは、更新からの戻りの使用についても間違っている可能性があります-ダースVが気難しい。

12
Chaos Crafter

カスケード削除を使用して、useridusers (id)の外部キーとして定義します。例:

create table users (
    id int primary key, 
    firstname text, 
    lastname text);

create table orders (
    orderid int primary key, 
    userid int references users (id) on delete cascade, 
    orderdate date, 
    total numeric);

delete from users
where firstname = 'Sam';
2
klin