Reputation: 736
I would like to be able to get values of function variables whose names are queried from a table
Edited to show querying a table instead of query from static values:
create table __test__
(
_col text
);
insert into __test__
(_col)
values('_a');
create or replace function __test()
returns void
language 'plpgsql' as
$$
declare
_r record;
_a int;
_b int;
_sql text;
begin
_a = 1;
_b = 0;
for _r in select _col as _nam from __test__ a loop
-- query returns one row valued "_a"
_sql = 'select ' || _r._nam ;
execute _sql into _b;
end loop;
raise info 'value of _b %', _b;
end;
$$;
select __test()
when function executes so that _b = 1. Is it possible?
same error ...
ERROR: column "_a" does not exist
LINE 1: select _a
^
QUERY: select _a
CONTEXT: PL/pgSQL function "__test" line 15 at EXECUTE statement
Upvotes: 0
Views: 3143
Reputation: 26454
You could create a temporary table, insert your variable names and values in it, and then execute a select against that. Just clean up after. I have used approaches like that before. It works ok. It does have extra overhead though.
Edit: adding an example
CREATE FUNCTION switch (in_var text) RETURNS text
LANGUAGE PLPGSQL VOLATILE AS $$
declare t_test text;
switch_vals text[];
BEGIN
CREATE TEMPORARY TABLE switch_values (var text, value text);
EXECUTE $e$ INSERT INTO switch_values VALUES
('a', '1'), ('b', '2'), ('c', '3') $e$;
EXECUTE $e$ SELECT value FROM switch_values WHERE var = $e$ || quote_literal(in_var)
INTO t_test;
DROP TABLE switch_values;
RETURN t_test;
END; $$;
postgres=# select switch('a');
switch
--------
1
(1 row)
Upvotes: 2
Reputation: 61516
Let's try to reframe the question: what you're after would be the equivalent of Perl eval()
function, with its ability to execute a dynamically generated piece of code for which "any outer lexical variables are visible to it". In your example, the variable would be _a
, but as you can see from the error message, it can't be interpolated by a dynamic SQL statement. The reason is that the SQL interpreter has no visibility on the current pl/pgsql variables, or even the knowledge that such variables exist. They are confined to pl/pgsql.
What would be needed here is a context-aware dynamically-generated pl/pgsql statement, but this language does not have this feature. It's doubtful that a trick could be found to achieve the result without this feature. For all its ability to interface nicely with SQL, other than that it's a fairly static language.
On the other hand, this would be no problem for pl/perl.
Upvotes: 2