declare @person_id int; set @person_id = 1; select * from person where person_id = @person_id;
On Postgres 9.0, though it already supports anonymous code block, it's constrained by the fact that the anonymous code block is encapsulated in an invisible void function(Postgres supports many procedural languages, not just its own flavor of procedural language(PL/pgSQL), e.g. Python, Java, Perl, LOLCODE, etc), well you can think of it that way. Hence displaying query results on anonymous code block won't work out-of-the-box on Postgres. This won't work:
do $$ declare _person_id int; begin _person_id = 1; select * from person where person_id = _person_id; end; $$;
That will produce this error:
ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function "inline_code_block" line 8 at SQL statement ********** Error ********** ERROR: query has no destination for result data SQL state: 42601 Hint: If you want to discard the results of a SELECT, use PERFORM instead. Context: PL/pgSQL function "inline_code_block" line 8 at SQL statement
Neither this will work:
do $$ declare _person_id int; begin _person_id = 1; return query select * from person where person_id = _person_id; end; $$;
That code will produce this error:
ERROR: cannot use RETURN QUERY in a non-SETOF function LINE 13: return query select * from person where person_id = _person... ^ ********** Error ********** ERROR: cannot use RETURN QUERY in a non-SETOF function SQL state: 42804 Character: 170
So if you want to test logic on-the-fly on Postgres, create temporary table on anonymous code block:
do $$ declare _person_id int; begin _person_id = 1; drop table if exists _x; create temporary table _x as select * from person where person_id = _person_id; end; $$; select * from _x; -- the temporary table will continue to exist on individual Postgres session
Wish for Postgres, make this happen, to make adhoc-y stuff happen :-)
do returns table (person_id int, lastname text) as $$ declare _person_id int; begin _person_id = 1; return query select person_id, lastname from person where person_id = _person_id; end; $$;
UPDATE: March 27, 2019
Made the code shorter:
do $$ declare _person_id int; begin _person_id = 1; create temporary table _x on commit drop as select * from person where person_id = _person_id; end; $$; select * from _x; -- the temporary table will continue to exist on individual Postgres session
With that code, there's no need to explicitly drop the table. Postgres has an implicit commit whenever queries are executed. on commit drop ensures that the temporary table will not stay in session longer than necessary.
Found out on commit drop here: https://stackoverflow.com/questions/22929365/create-a-temp-table-if-not-exists-for-use-into-a-custom-procedure/22932917#22932917
Run into this problem for the second time and found your tip on both occassions :) It seems like I have a memory leak, ha-ha.
ReplyDeleteThanks
Been looking for solution for this. You saved me lot of effort!!!!
ReplyDeleteIs there a way to avoid the $$, to use in code?
ReplyDeleteThis is SUPER important, but for some reason, coming across this information isn't easy. Thank you.
ReplyDeleteThanks
ReplyDeleteMichael:-
ReplyDelete/*
Begin explicit transaction
*/
begin transaction;
DO
$$
begin
drop table if exists _x;
create temporary table _x
-- on commit drop
-- on commit preserve
-- on commit delete rows
as
select
1 as id
union all
select
2 as id
;
/*
return query
select
1 as a
;
*/
end;
$$;
select *
from _x
;
/*
Commiting or Rolling back the explicit transaction results in a empty table
*/
-- commit;
rollback ;
Please help me understanding why adding a rollback at the end triggers and empty record set.