Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I insert the return of DELETE into INSERT in postgresql?

I am trying to delete a row from one table and insert it with some additional data into another. I know this can be done in two separate commands, one to delete and another to insert into the new table. However I am trying to combine them and it is not working, this is my query so far:

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

When running that I get the following error:

ERROR: syntax error at or near "delete"

Can anyone point out how to accomplish this, or is there a better way? or is it not possible?

like image 933
lanrat Avatar asked Jul 05 '11 03:07

lanrat


People also ask

What does Postgres return on insert?

In an INSERT , the data available to RETURNING is the row as it was inserted. This is not so useful in trivial inserts, since it would just repeat the data provided by the client. But it can be very handy when relying on computed default values.

How do I return a record in PostgreSQL?

To return a table from the function, you use RETURNS TABLE syntax and specify the columns of the table. Each column is separated by a comma (, ). In the function, we return a query that is a result of a SELECT statement.

What does returning * mean in Postgres?

The RETURNING keyword in PostgreSQL gives you an opportunity to return, from the insert or update statement, the values of any columns after the insert or update was run.

How does delete work in PostgreSQL?

Description. DELETE deletes rows that satisfy the WHERE clause from the specified table. If the WHERE clause is absent, the effect is to delete all rows in the table. The result is a valid, but empty table.


3 Answers

You cannot do this before PostgreSQL 9.1, which is not yet released. And then the syntax would be

WITH foo AS (DELETE FROM a WHERE id = 1 RETURNING one, two, 5)
    INSERT INTO b (one, two, num) SELECT * FROM foo;
like image 123
Peter Eisentraut Avatar answered Oct 08 '22 19:10

Peter Eisentraut


Before PostgreSQL 9.1 you can create a volatile function like this (untested):

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;
$$

And then just use select move_from_a_to_b(1, 5). A function has the advantage over two statements that it will always run in single transaction — there's no need to explicitly start and commit transaction in client code.

like image 35
Tometzky Avatar answered Oct 08 '22 21:10

Tometzky


For all version of PostgreSQL, you can create a trigger function for deleting rows from a table and inserting them to another table. But it seems slower than bulk insert that is released in PostgreSQL 9.1. You just need to move the old data into the another table before it gets deleted. This is done with the OLD data type:

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();

As above answer, after PostgreSQL 9.1 you can do this:

WITH tmp AS (DELETE FROM table RETURNING column1, column2, ...)
    INSERT INTO another_table (column1, column2, ...) SELECT * FROM tmp;
like image 20
Khalil Avatar answered Oct 08 '22 19:10

Khalil