November 3rd, 2008 by depesz | Tags: , , , , | No comments »
Did it help? If yes - maybe you can help me? Donate BTC to 19zPa5diT2LZqGtTi8f8bfApLn8rw9zBHx

In PostgreSQL 8.2, we got “RETURNING" clause in INSERT/UPDATE/DELETE queries.

Unfortunately it could not be used as source of rows for anything in sql.

insert into table_backup delete from table where ... returning *;

Well, it's still not possible, but it is a one step closer, thanks to patch written and committed by Tom Lane on 31st of October:

Allow SQL-language functions to return the output of an INSERT/UPDATE/DELETE
RETURNING clause, not just a SELECT as formerly.
 
A side effect of this patch is that when a set-returning SQL function is used
in a FROM clause, performance is improved because the output is collected into
a tuplestore within the function, rather than using the less efficient
value-per-call mechanism.

How does it work? It's pretty simple. Let's start with test table:

# create table test (i int4);
CREATE TABLE

With some test content:

# insert into test select generate_series(1, 10);
INSERT 0 10

Now, let's create our sql function which will delete rows:

CREATE function delete_from_test_returning(INT4) RETURNS setof test as $$
DELETE FROM test WHERE i <= $1 returning *
$$ language sql;

As you can see the function is pretty simple.

Now, let's use it to backup removed rows:

# create table delete_backup as select * from delete_from_test_returning(3);
SELECT

And check the content of tables:

# select * from test;
i
----
4
5
6
7
8
9
10
(7 rows)

# select * from delete_backup;
i
---
1
2
3
(3 rows)

Of course I could have done it before with pl/PgSQL function that would iterate over returned rows, but this approach will be definitely faster.

Leave a comment