如何在postgresql中将DELETE的返回值插入INSERT?

时间:2011-07-05 03:55:10

标签: postgresql sql-insert sql-delete

我正在尝试从一个表中删除一行,并将一些其他数据插入到另一个表中。我知道这可以在两个单独的命令中完成,一个用于删除,另一个用于插入新表。但是我试图将它们组合起来并且它不起作用,这是我到目前为止的查询:

insert into b (one,two,num) values delete from a where id = 1 returning one, two, 5;

运行时,我收到以下错误:

  

错误:“删除”或附近的语法错误

任何人都可以指出如何实现这一目标,还是有更好的方法?还是不可能?

5 个答案:

答案 0 :(得分:42)

在PostgreSQL 9.1尚未发布之前,你无法做到这一点。然后语法将是

WITH foo AS (DELETE FROM a WHERE id = 1 RETURNING one, two, 5)
    INSERT INTO b (one, two, num) SELECT * FROM foo;

答案 1 :(得分:5)

在PostgreSQL 9.1之前,您可以创建一个像(未经测试)这样的易失性函数:

create function move_from_a_to_b(_id integer, _num integer)
returns void language plpgsql volatile as
$$
  declare
    _one integer;
    _two integer;
  begin
    delete from a where id = _id returning one, two into strict _one, _two;
    insert into b (one,two,num) values (_one, _two, _num);
  end;
$$

然后只使用select move_from_a_to_b(1, 5)。函数优于两个语句,它总是在单个事务中运行 - 不需要在客户端代码中显式启动和提交事务。

答案 2 :(得分:1)

对于所有版本的PostgreSQL,您可以创建一个触发器函数,用于从表中删除行并将它们插入另一个表。但它似乎比PostgreSQL 9.1中发布的批量插入慢。您只需要在删除之前将旧数据移动到另一个表中。这是通过OLD数据类型完成的:

CREATE FUNCTION moveDeleted() RETURNS trigger AS $$
    BEGIN
        INSERT INTO another_table VALUES(OLD.column1, OLD.column2,...);
        RETURN OLD;
    END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER moveDeleted
BEFORE DELETE ON table 
    FOR EACH ROW
        EXECUTE PROCEDURE moveDeleted();

如上所述,在PostgreSQL 9.1之后你可以这样做:

WITH tmp AS (DELETE FROM table RETURNING column1, column2, ...)
    INSERT INTO another_table (column1, column2, ...) SELECT * FROM tmp;

答案 3 :(得分:0)

您所拥有的语法无效。 2个语句是执行此操作的最佳方式。最直观的方法是首先执行插入操作,然后执行删除操作。

答案 4 :(得分:-1)

作为“AI W”,两个陈述当然是最适合您的选择,但您也可以考虑为此编写触发器。每次在第一张表中删除某些内容时,都会填写另一张内容。