1

我有两张桌子t1t2. 我正在以t2这种方式删除某些行:

delete from t2 where expiry < NOW();

和有一个id共同t1的列t2。执行上述语句时,我还想删除相应的行(t1如果有)(可能没有)。

如何才能做到这一点?
是否可以为这两个操作编写一个查询?

4

1 回答 1

2

我看到至少三种好方法 - 取决于您的问题中缺少的更多细节。我以您的示例为基础:

  • t2是母桌
  • t1孩子

1.外键约束ON 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.触发AFTER DELETE

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

触发功能:

CREATE OR REPLACE FUNCTION t2_delaft
  RETURNS trigger 
  LANGUAGE plpgsql AS
$func$
BEGIN
   DELETE FROM t1
   WHERE  t1.id = OLD.id;

   RETURN NULL;  -- AFTER trigger can return NULL
END
$func$

扳机:

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

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

3.数据修改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;
于 2012-06-16T03:49:54.670 回答