Postgresql 从多个表中删除多行

问题描述 投票:0回答:3

考虑 2 个或更多桌子:

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

我希望删除所有与名字“Sam”匹配的用户及其订单。在mysql中,我通常做左连接。在此示例中,我们不知道 userid。

查询的正确格式是什么?

sql database postgresql relational-database sql-delete
3个回答
49
投票

安排适当的级联删除是明智的,通常是正确的解决方案。 对于某些特殊情况,还有另一种相关的解决方案。

如果您需要基于一组通用数据执行多次删除,可以使用通用表表达式 (CTE)

很难想出一个简单的示例,因为主要用例可以通过级联删除来覆盖。

对于这个例子,我们将删除表 A 中的所有项目,其值在我们要从表 B 中删除的值集中。通常这些项目是键,但如果不是,则不能进行级联删除使用过。

要解决这个问题,您可以使用 CTE

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

这个例子故意简单,因为我的观点不是争论键映射等,而是展示如何在共享数据集上执行两个或多个删除。 这也可能更复杂,包括更新命令等。

这是一个更复杂的例子(来自达斯·维德的个人数据库)。在本例中,我们有一个引用地址表的表。如果地址在他摧毁的行星列表中,我们需要从地址表中删除这些地址。我们希望使用此信息从人员表中删除,但前提是他们在地球上(或在他的战利品杀戮列表中)

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 在使用从更新返回时也可能是错误的 - 我无法测试运行它,因为 Darth V. 在脾气暴躁。


29
投票

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

8
投票

正确的数据模型设计至关重要,尤其是在数据库领域。利用关系数据库系统提供的本机可能性。将

userid
定义为
users (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';
© www.soinside.com 2019 - 2024. All rights reserved.