【问题标题】:How can I insert the return of DELETE into INSERT in postgresql?如何将 DELETE 的返回值插入到 postgresql 中的 INSERT 中?
【发布时间】:2011-09-28 12:01:45
【问题描述】:

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

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

运行时出现以下错误:

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

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

【问题讨论】:

    标签: postgresql sql-insert sql-delete


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        在尚未发布的 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;
        

        【讨论】:

        • 非常感谢您的回答,当我迁移到 9.1 时,我将使用它,现在必须使用 Tometzky 的方法。
        • 很好的答案,因为大多数人都在使用远高于 9.1 的版本。无需触发器。
        • 文档也有类似的例子,并进入一些more detail
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          对于所有版本的 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;
          

          【讨论】:

          • 如果您想移动一些行,请说明在哪里添加 WHERE 子句。 DELETE FROM table WHERE <condition> RETURNING...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多