Postgresql 从多个表中删除多行
Postgresql delete multiple rows from multiple tables
考虑 2 个或更多表:
users (id, firstname, lastname)
orders (orderid, userid, orderdate, total)
我想删除所有 用户 和他们的 订单 匹配名字 'Sam '.在 mysql 中,我通常使用 left join。在此示例中,我们不知道用户 ID。
查询的正确格式是什么?
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
创建 table
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)
);
将 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';
安排适当的级联删除是明智的,通常是解决此问题的正确方法。
对于某些特殊情况,还有另一种相关的解决方案。
如果您需要根据一组通用数据执行多次删除,您可以使用 Common Table Expressions (CTE)。
很难想出一个简单的例子,因为级联删除可以涵盖此的主要用例。
例如,我们将删除 table A 中的所有项,其值在我们要从 table B 中删除的值集中。通常这些是键,但是如果没有,则无法使用级联删除。
要解决这个问题,您可以使用 CTE
WITH Bdeletes AS (
DELETE from B where IsSomethingToDelete = true returning ValueThatRelatesToA
)
delete from A where RelatedValue in (select ValueThatRelatesToA from Bdeletes)
这个例子特意简单了,因为我的意思不是争论键映射等,而是展示如何在共享数据集上执行两次或更多次删除。
这也可能更复杂,包括更新命令等。
这是一个更复杂的例子(来自黑武士的个人数据库)。在这种情况下,我们有一个引用地址 table 的 table。我们需要从地址 table 中删除地址,如果它们在他被摧毁的行星列表中。我们想使用此信息从人员 table 中删除,但前提是他们在星球上(或在他的战利品杀人名单上)
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 中删除(我的 SQL 在使用从更新返回时也可能是错误的 - 我无法测试 运行这是因为 Darth V. 心情暴躁。
考虑 2 个或更多表:
users (id, firstname, lastname)
orders (orderid, userid, orderdate, total)
我想删除所有 用户 和他们的 订单 匹配名字 'Sam '.在 mysql 中,我通常使用 left join。在此示例中,我们不知道用户 ID。
查询的正确格式是什么?
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)
);
将 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';
安排适当的级联删除是明智的,通常是解决此问题的正确方法。 对于某些特殊情况,还有另一种相关的解决方案。
如果您需要根据一组通用数据执行多次删除,您可以使用 Common Table Expressions (CTE)。
很难想出一个简单的例子,因为级联删除可以涵盖此的主要用例。
例如,我们将删除 table A 中的所有项,其值在我们要从 table B 中删除的值集中。通常这些是键,但是如果没有,则无法使用级联删除。
要解决这个问题,您可以使用 CTE
WITH Bdeletes AS (
DELETE from B where IsSomethingToDelete = true returning ValueThatRelatesToA
)
delete from A where RelatedValue in (select ValueThatRelatesToA from Bdeletes)
这个例子特意简单了,因为我的意思不是争论键映射等,而是展示如何在共享数据集上执行两次或更多次删除。 这也可能更复杂,包括更新命令等。
这是一个更复杂的例子(来自黑武士的个人数据库)。在这种情况下,我们有一个引用地址 table 的 table。我们需要从地址 table 中删除地址,如果它们在他被摧毁的行星列表中。我们想使用此信息从人员 table 中删除,但前提是他们在星球上(或在他的战利品杀人名单上)
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 中删除(我的 SQL 在使用从更新返回时也可能是错误的 - 我无法测试 运行这是因为 Darth V. 心情暴躁。