如何从多个表中删除数据?

时间:2012-04-13 17:07:54

标签: sql postgresql foreign-keys sql-delete

我有这些表格:

event     (evt_id, evt_code, reg_id)

magnitude (mag_id, evt_id, value)

trace     (trace_id, pt_id)

point     (pt_id, evt_id)

我想删除与evt_id=1139相关的所有表格中的所有行 我该怎么做?

5 个答案:

答案 0 :(得分:18)

如果您可以控制架构,我会使架构使用cascading deletes

从文章(为您的示例翻译的更相关的部分)

CREATE TABLE point
(
    pt_id integer PRIMARY KEY,
    evt_id integer REFERENCES event ON DELETE CASCADE
)

如果您设置了级联,那么您只需从主事件表中删除,所有其他表格将自动清理

否则,您需要先删除所有引用,然后删除主表。您应该在一个事务中执行此操作以保持数据一致

BEGIN;
DELETE FROM trace WHERE EXISTS 
    (SELECT 1 FROM point WHERE evt_id = 1139 AND trace.pt_id = point.pt_id);
DELETE FROM point where evt_id = 1139;
DELETE FROM magnitude where evt_id = 1139;
DELETE FROM event where evt_id = 1139;
COMMIT;

答案 1 :(得分:11)

您问题中唯一的重要元素是表trace中的删除。我想可以安全地假设trace.pt_id引用了point.pt_id

要么定义foreign key with ON DELETE CASCADE而忘记表trace(已经是pointed out by @kevin),要么必须手动处理依赖行。

自PostgreSQL 9.1 以来,您可以使用data-modifying CTEs

BEGIN;

WITH x AS (
    DELETE FROM point WHERE evt_id = 1139
    RETURNING pt_id
    )
DELETE FROM trace
USING x
WHERE trace.pt_id = x.pt_id;

DELETE FROM magnitude WHERE evt_id = 1139;

DELETE FROM event WHERE evt_id = 1139;

COMMIT;

DELETE FROM point的{​​{3}}会返回所有受影响的pt_id - 这些用于删除trace中的所有相应行。

您没有提及并发在您的案例中是否存在问题。如果是,并且如果您希望在删除之间的短时间窗口中避免可能的结果,其中evt_id = 1139的行存在于一个表中而已从另一个表中删除,则将其全部包装到事务中
如果您不关心这一点,请忽略BEGINCOMMIT

要避免死锁,请始终使用相同的删除语句序列(在所有并发事务中)。这可以避免一个事务在一个表中开始删除,另一个表中的下一个事务处理,然后每个事务将等待另一个事务的情况。

答案 2 :(得分:4)

如果要删除的行可以设想为层次结构,则可以为ON DELETE CASCADE子句的关系定义FOREIGN KEY约束。删除顶部的行将向下级联并将其全部删除。

http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK

答案 3 :(得分:-3)

我假设不同表中的id对应并用于链接。 我还假设您要删除所有跟踪点,尽管它们只是间接链接到evt_id

您可以按如下方式从所有表中删除记录:

DELETE event , magnitude, trace, point
FROM event left join magnitude on event.evt_id = magnitude.evt_id
   left join point on event.evt_id = point.evt_id
       left join trace on point.pt_id = trace.trace_id
where event_id=1139

答案 4 :(得分:-4)

$delete =  1139;
$query = "DELETE FROM event, magnitude, point WHERE evt_id = '$delete'";
mysql_query($query, $con);
$query = "DELETE FROM trace WHERE pt_id = '$delete'";

或者只是将该语句粘贴到.sql文件中并运行它,或者将其粘贴到sql软件查询窗口中,或者将其放在.php文件中并在服务器上运行。