简体   繁体   English

Postgresql从多个表中删除多行

[英]Postgresql delete multiple rows from multiple tables

Consider 2 or more tables: 考虑2个或更多表:

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

I wish to delete all users and their orders that match first name ' Sam '. 我希望删除与名字“ Sam ”匹配的所有用户及其订单 In mysql, I usually do left join. 在mysql中,我通常会离开加入。 In this example userid is unknown to us. 在此示例中,userid对我们来说是未知的。

What is the correct format of the query? 查询的正确格式是什么?

http://www.postgresql.org/docs/current/static/sql-delete.html 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';

You can also create the table with ON delete cascade 您还可以使用ON delete cascade创建表

http://www.postgresql.org/docs/current/static/ddl-constraints.html 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)
);

Arranging proper cascading deletes is wise and is usually the correct solution to this. 安排适当的级联删除是明智的,通常是正确的解决方案。 For certain special cases, there is another solution to this that can be relevant. 对于某些特殊情况,还有另一种可能相关的解决方案。

If you need to perform multiple deletes based on a common set of data you can use CTEs 如果需要根据一组通用数据执行多次删除,则可以使用CTE

It's hard to come up with a simple example as the main use case for this can be covered by cascading deletes. 很难想出一个简单的例子,因为这个主要用例可以通过级联删除来解决。

For the example we're going to delete all items in table A whose value is in the set of values we're deleting from table B. Usually these would be keys, but where they are not, then cascading delete can't be used. 对于该示例,我们将删除表A中的所有项,其值在我们从表B中删除的值集中。通常这些是键,但在不是,但是不能使用级联删除。

To solve this you use CTEs 要解决此问题,请使用CTE

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

This example is deliberately simple because my point is not to argue over key mapping etc, but to show how two or more deletes can be performed off a shared dataset. 这个例子是故意简单的,因为我的观点不是争论密钥映射等,而是说明如何从共享数据集中执行两个或多个删除。 This can be much more complex too, including update commands etc. 这也可能更复杂,包括更新命令等。

Here is a more complex example (from Darth Vader's personal database). 这是一个更复杂的例子(来自Darth Vader的个人数据库)。 In this case, we have a table that references an address table. 在这种情况下,我们有一个引用地址表的表。 We need to delete addresses from the address table if they are in his list of planets he's destroyed. 我们需要删除地址表中的地址,如果它们在他被摧毁的行星列表中。 We want to use this information to delete from the people table, but only if they were on-planet (or on his trophy-kill list) 我们希望使用此信息从人员表中删除,但仅限于他们在地球上(或在他的奖杯 - 杀戮名单上)

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)

Now his database is up to date. 现在他的数据库是最新的。 No integrity failures due to Address deletion. 没有因地址删除导致的完整性故障。 Note that while we are returning data from the update and the first delete, it doesn't mean we have to use it. 请注意,虽然我们从更新和第一次删除返回数据,但这并不意味着我们必须使用它。 I'm uncertain whether you can put a delete in a CTE with no returned data (My SQL may also be wrong on the use of returning from an update - I've not been able to test run this as Darth V. was in a cranky mood. 我不确定你是否可以在没有返回数据的CTE中删除(我的SQL在使用从更新返回时可能也是错误的 - 我无法测试运行这个因为Darth V.是在胡思乱想的心情。

Define userid as a foreign key to users (id) with cascading delete, eg: 使用级联删除将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';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM