根据从另一个表中删除的行,从表中删除行

时间:2012-06-15 08:20:40

标签: sql postgresql

我有两个表t1和t2。我这样删除某些t2行:

delete from t2 where expiry<NOW();

t1和t2共有一列id。但是不确定t2中的id将始终在t1中具有相应的行。执行上述语句时,我还想根据id删除t1中的相应行(如果它们存在,则仅从t2删除)。如何才能做到这一点?是否可以编写单个查询来完成这两项操作?

1 个答案:

答案 0 :(得分:2)

我至少看到了三种好方法 - 取决于你问题中遗漏的更多细节。我建立在你的榜样上:

  • t2是母亲表
  • t1孩子

1。 Foreign key constraintON CASCADE DELETE

试验台:

CREATE TABLE t2 (
  id serial PRIMARY KEY  -- primary or unique key needed
 ,expiry timestamp
);

CREATE TABLE t1(
  id int references t1(id) ON DELETE CASCADE  -- ON UPDATE CASCADE, too?
);

填充表格:

INSERT INTO t2(expiry)
SELECT (now() + g * interval '1h')
FROM   generate_series(1, 10) g;   -- 10 arbitrary rows

INSERT INTO t1(id)
SELECT id FROM t2 WHERE id%2 = 0;  -- pick even numbers for t1

SELECT * FROM t1;

如果从t2删除行,则会自动删除t1中的相应行:

DELETE FROM t2 WHERE id IN (1,2,3,4,5);
-- rows 2,4 in `t1` are deleted automatically

将这样的外键约束添加到现有表中:

ALTER TABLE t1 ADD CONSTRAINT t1_id_fkey FOREIGN KEY (id)
REFERENCES t2 (id) ON DELETE CASCADE;

当然,外键需要t1.id上的唯一键或主键。但你可能在这样的场景中有这个。

2。 Trigger AFTER DELETE

如果t2.id中的值不唯一,或者t1.id中的值违反了外键约束,则可以改为创建触发器AFTER DELETE。

触发功能:

CREATE OR REPLACE FUNCTION t2_delaft
  LANGUAGE plpgsql VOLATILE
  RETURNS trigger AS
$BODY$
BEGIN

DELETE FROM t1
WHERE  t1.id = OLD.id;

RETURN NULL;  -- AFTER trigger can return NULL

END;
$BODY$

触发:

CREATE TRIGGER delaft
AFTER DELETE ON t2
FOR EACH ROW EXECUTE PROCEDURE t2_delaft();

您还可以实施RULE。但我发现触发器通常更容易处理。

3。 Data modifying CTE

原谅我最后给出最简单的答案。无论如何,这都有效 - 只要您使用的是PostgreSQL 9.1或更高版本

WITH x AS (
    DELETE FROM t1
    WHERE  id IN (1,2,3,4,5)
    RETURNING id
    )
DELETE FROM t2
USING  x
WHERE  t2.id = x.id;
相关问题