Обсуждение: plpgsql select into
Hello, I want to take a multiline text column from one table, split it into rows and insert it into another table. Eventually this function will also need insert the 'id' field and a timestamp into the other table but for now I'm focused on dealing with the multiline text. I could code all this up in C++ but I'm doing it as a plpgsql function so that the function can be called from a trigger when the data are inserted into the database. So far an exercise in frustration. Here is may latest effort: CREATE OR REPLACE FUNCTION get_info (id text) RETURNS TABLE ( tabular_info text ) AS $function$ BEGIN RETURN query WITH a AS ( SELECT regexp_split_to_table(info_out, '\n') AS info FROM public.results WHERE public.results.jid = id ) SELECT * INTO tabular_info FROM a RETURN; END; $function$ LANGUAGE plpgsql; I execute the function: select get_info('1043_1'); ERROR: cannot open SELECT query as cursor CONTEXT: PL/pgSQL function get_info(text) line 3 at RETURN QUERY Perhaps what I'm trying to do is impossible, in which case it would be useful to know if a trigger can be set up to call out to an external command. I appreciate any help offered. Thanks, Roger
Roger Mason <rmason@mun.ca> writes: > CREATE OR REPLACE FUNCTION get_info (id text) > RETURNS TABLE ( > tabular_info text > ) > AS $function$ > BEGIN > RETURN query WITH a AS ( > SELECT > regexp_split_to_table(info_out, '\n') AS info > FROM > public.results > WHERE > public.results.jid = id > ) > SELECT > * INTO tabular_info > FROM > a RETURN; > END; > $function$ > LANGUAGE plpgsql; You need to drop the "INTO tabular_info" bit, as the RETURN QUERY context already dictates where the results should go. Possibly we could improve the error message. It's already been changed somewhat in v14/HEAD: I get ERROR: query "WITH a AS ( SELECT regexp_split_to_table(info_out, '\n') AS info FROM public.results WHERE public.results.jid = id ) SELECT * INTO tabular_info FROM a RETURN" is not a SELECT CONTEXT: PL/pgSQL function get_info(text) line 3 at RETURN QUERY Looking at this, though, I'm pretty unhappy with it. It would be more readable to put the query text last, or maybe even as a CONTEXT line. But the real issue is that it's still not making the point that SELECT INTO is different from plain SELECT. Perhaps we should special-case that, with say "query is SELECT INTO, but it should be a plain SELECT". regards, tom lane
On Fri, 2021-08-20 at 08:08 -0230, Roger Mason wrote: > CREATE OR REPLACE FUNCTION get_info (id text) > RETURNS TABLE ( > tabular_info text > ) > AS $function$ > BEGIN > RETURN query WITH a AS ( > SELECT > regexp_split_to_table(info_out, '\n') AS info > FROM > public.results > WHERE > public.results.jid = id > ) > SELECT > * INTO tabular_info > FROM > a RETURN; > END; > $function$ > LANGUAGE plpgsql; > > I execute the function: > > select get_info('1043_1'); > > ERROR: cannot open SELECT query as cursor > CONTEXT: PL/pgSQL function get_info(text) line 3 at RETURN QUERY Omit "INTO tabular_info" from the query. RETURN QUERY already is a destination for the query result. Yours, Laurenz Albe -- Cybertec | https://www.cybertec-postgresql.com
Hello Tom & Laurenz, Thanks for your responses. Laurenz Albe writes: > Omit "INTO tabular_info" from the query. > RETURN QUERY already is a destination for the query result. Yes, if I omit the INTO clause I get data returned. So then how do I insert the result of the plpgsql call into a table? This is what happens if I try calling 'select into' in psql: select into info_table from (select get_info('1043_1')) as info_split; SELECT 1288 test=> select * from info_table ; -- (1288 rows) How do I access the data in 'info_table'? Thanks, Roger
Roger Mason <rmason@mun.ca> writes: > Yes, if I omit the INTO clause I get data returned. So then how do I > insert the result of the plpgsql call into a table? This is what > happens if I try calling 'select into' in psql: > select into info_table from (select get_info('1043_1')) as info_split; > SELECT 1288 > test=> select * from info_table ; > -- > (1288 rows) You selected zero columns (which psql is not very good at displaying :-(). Try select * into info_table from (select get_info('1043_1')) as info_split; BTW, that could be simplified a lot: select * into info_table from get_info('1043_1'); regards, tom lane
On Fri, Aug 20, 2021 at 8:51 AM Roger Mason <rmason@mun.ca> wrote:
select into info_table from (select get_info('1043_1')) as info_split;
I suggest you should pretend that SQL's "SELECT INTO" doesn't exist. If you want to create a table from a result write: "CREATE TABLE AS" and then a normal select query. In particular the entire "action" command is kept whole instead of needing to put a bunch of column names in between the "SELECT" and the "INTO" - and you also are less likely to confuse the plpgsql feature of the same form.
David J.
Tom Lane writes: > Roger Mason <rmason@mun.ca> writes: > You selected zero columns (which psql is not very good at displaying :-(). > Try > > select * into info_table from (select get_info('1043_1')) as info_split; > > BTW, that could be simplified a lot: > > select * into info_table from get_info('1043_1'); Embarassed cough :-). And thanks for the simplification. Roger
David G. Johnston writes: > I suggest you should pretend that SQL's "SELECT INTO" doesn't exist. If > you want to create a table from a result write: "CREATE TABLE AS" and then > a normal select query. In particular the entire "action" command is kept > whole instead of needing to put a bunch of column names in between the > "SELECT" and the "INTO" - and you also are less likely to confuse the > plpgsql feature of the same form. Thank you David. I will try to heed that advice. Roger