23

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

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

运行时出现以下错误:

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

谁能指出如何做到这一点,或者有更好的方法吗?还是不可能?

4

5 回答 5

63

在尚未发布的 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;
于 2011-07-05T06:31:16.113 回答
8

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

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). 与两个语句相比,函数的优势在于它始终在单个事务中运行——无需在客户端代码中显式启动和提交事务。

于 2011-07-05T16:01:50.513 回答
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;
于 2013-07-23T09:33:40.110 回答
-1

您那里的语法无效。2 语句是最好的方法。最直观的方法是先插入,再删除。

于 2011-07-05T03:57:47.627 回答
-1

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

于 2011-07-05T06:03:23.990 回答