我正在尝试从一个表中删除一行,并将一些其他数据插入到另一个表中。我知道这可以在两个单独的命令中完成,一个用于删除,另一个用于插入新表。但是我试图将它们组合起来并且它不起作用,这是我到目前为止的查询:
insert into b (one,two,num) values delete from a where id = 1 returning one, two, 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”,两个陈述当然是最适合您的选择,但您也可以考虑为此编写触发器。每次在第一张表中删除某些内容时,都会填写另一张内容。