I want to execute query with ltree param in plpgsql function... but i can`t understand how to use quotes in this functions...
CREATE OR REPLACE FUNCTION f_select(BIGINT) RETURNS setof categories AS
$$
DECLARE
s_cat ALIAS FOR $1;
queryText TEXT;
result categories%ROWTYPE;
BEGIN
queryText := 'SELECT * FROM categories WHERE cat_tree ~ \'*.\'|| s_cat::text ||\'.*\'';
FOR result IN EXECUTE queryText
LOOP
RETURN NEXT result;
END LOOP;
RETURN;
END
$$
LANGUAGE plpgsql;
How to do this ???
After executing this code in psql I get error:
ERROR: syntax error at or near "."
LINE 10: ... := 'SELECT * FROM categories WHERE cat_tree ~ \'*.\'|| s_ca...
Final working verison:
CREATE OR REPLACE FUNCTION f_select(BIGINT) RETURNS setof categories AS
$$
DECLARE
s_cat ALIAS FOR $1;
queryText TEXT;
result categories%ROWTYPE;
BEGIN
queryText := 'SELECT * FROM categories WHERE cat_tree ~ ''' || ('*.'|| s_cat::text || '.*')::lquery || '''';
FOR result IN EXECUTE queryText
LOOP
RETURN NEXT result;
END LOOP;
RETURN;
END
$$
LANGUAGE plpgsql;
The problem seems to be misusing the backslash, but anyway putting this query into a text variable shouldn't be needed in the first place.
What about this form:
FOR result IN SELECT * FROM categories WHERE cat_tree ~ '*.'|| s_cat::text || '.*'
LOOP
RETURN NEXT result;
END LOOP;
And if the LOOP just has to return the results, you may just as well avoid it and return the query directly:
RETURN QUERY SELECT * FROM categories WHERE cat_tree ~ '*.'|| s_cat::text || '.*';
EDIT:
Since the operator is ltree ~ lquery and ~ binds tighter than ||, the right operand should be parenthesized and cast to lquery:
RETURN QUERY SELECT * FROM categories
WHERE cat_tree ~ ('*.'|| s_cat::text || '.*')::lquery;
Related
I have a function that takes 3 parameters: huc, id_list, and email.
CREATE OR REPLACE FUNCTION my_app.job_batch(
huc text,
input_list text[],
email text
) RETURNS VOID AS
$$
DECLARE
id text;
BEGIN
FOREACH id IN ARRAY input_list LOOP
EXECUTE 'SELECT * FROM my_app.my_funct(
' || huc || '::text,
' || id || '::text,
' || email || '::text)';
END LOOP;
END;
$$
LANGUAGE plpgsql;
When I try to run the function however, it throws an error: ERROR: column "myhu4" does not exist
SELECT * FROM spg_app.append_spg_job_batch('MYHUC4', array['1021', '1025','1026','1027','0701','0702','0703','0708','0709'], 'myemail#gmail.com');
Why is it referring to myhuc4 as a column and why is displaying it in lower case. Is my syntax below to run the function with those 3 parameters incorrect? Note: If I run the below hardcoded version, it runs fine:
DO $$
DECLARE
id_list text[] := array['1021', '1025','1026','1027','0701','0702','0703','0708','0709'];
id text;
BEGIN
FOREACH id in ARRAY id_list LOOP
EXECUTE 'SELECT * FROM my_app.my_funct(
''MYHU4''::text,
' || id || '::text,
''myemail#gmail.com''::text)'
END LOOP;
END;
$$
LANGUAGE plpgsql;
I suggest to use parameters instead of bad practice of stitching strings, as follows:
CREATE OR REPLACE FUNCTION my_app.job_batch(
huc text,
input_list text[],
email text
) RETURNS VOID AS
$$
DECLARE
id text;
BEGIN
FOREACH id IN ARRAY input_list LOOP
execute format ('SELECT * FROM my_app.my_funct($1, $2, $3)')
using huc, id, email;
END LOOP;
END;
$$
LANGUAGE plpgsql;
as shown in official docs https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
I would like to use cursor in a function with the table name as a function variable, a simple example would be a select query through cursor.
From the documentation of PostgreSQL I found that I can use
Declare curs3 CURSOR (key integer) FOR SELECT * FROM tenk1 WHERE unique1 = key;
But when I input
declare curs1 cursor (key integer) for execute 'select ' || quote_ident(colname) || ' from ' || quote_ident(tablename);
It returns ERROR: syntax error at or near "'select '".
On the other hand, if I write the function with refcursor as follows:
CREATE or replace FUNCTION cursor_hw(colname text,tablename text) RETURNS setof text AS $$
declare curs1 refcursor;
BEGIN
open curs1 for execute 'select ' || quote_ident(colname) || ' from ' || quote_ident(tablename);
for x in curs1 loop
return next x;
end loop;
END; $$ LANGUAGE plpgsql;
It will return [42601] ERROR: cursor FOR loop must use a bound cursor variable.
Any help would be appreciated, thanks a lot!
You may prefer a simple FOR record_variable IN EXECUTE <query> instead of OPEN FETCH for dynamic SQL.
CREATE or replace FUNCTION cursor_hw(colname text,tablename text)
RETURNS setof text AS
$$
DECLARE
x RECORD;
BEGIN
FOR x IN execute 'select ' || quote_ident(colname) || ' from '
|| quote_ident(tablename)
LOOP
IF x.first_name like 'D%' THEN
RETURN NEXT x;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
execution
knayak=# select cursor_hw('first_name','employees');
cursor_hw
-----------
Donald
Douglas
David
Diana
Daniel
Den
David
Danielle
David
(9 rows)
How to change "EXECUTE sql_string" to "RETURN QUERY" in a function declaration, but there is a where array which must be used.
In other words, how to change this
p_sql := 'SELECT *
FROM tbl
WHERE ' || array_to_string(where_arr, ' AND ');
FOR item IN EXECUTE p_sql
LOOP
RETURN NEXT item;
END LOOP;
to this
RETURN QUERY
SELECT *
FROM tbl
WHERE || array_to_string(where_arr, ' AND '); -- this is the place
I want my editors (phpstorm, notepad++) to see SQL as SQL and not as string.
https://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-STATEMENTS-RETURNING
return query execute $$
select *
from tbl
where $$ || array_to_string(where_arr, ' and ');
I can't figure out how to access variables inside my plpgsql function. I'm using postgres 9.5 under Cygwin.
functions.sql
-- this works fine
\echo Recreate = :oktodrop
CREATE OR REPLACE FUNCTION drop_table(TEXT) RETURNS VOID AS
$$
BEGIN
IF EXISTS ( SELECT * FROM information_schema.tables WHERE table_name = $1 ) THEN
-- syntax error here:
IF (:oktodrop == 1 ) THEN
DROP TABLE $1;
END IF;
END IF;
END;
$$
language 'plpgsql';
psql.exe -v oktodrop=1 -f functions.sql
Password:
Recreate = 1
psql:functions.sql:13: ERROR: syntax error at or near ":"
LINE 5: IF (:oktodrop == 1 ) THEN
^
Perhaps I've oversimplified your task (feel free to tell me if that's the case), but why not create the function like this:
CREATE OR REPLACE FUNCTION drop_table(tablename TEXT, oktodrop integer)
RETURNS text AS
$$
DECLARE
result text;
BEGIN
IF EXISTS ( SELECT * FROM information_schema.tables WHERE table_name = tablename ) THEN
IF (oktodrop = 1 ) THEN
execute 'DROP TABLE ' || tablename;
result := 'Dropped';
ELSE
result := 'Not Okay';
END IF;
ELSE
result := 'No such table';
END IF;
return result;
END;
$$
language 'plpgsql';
Then the implementation would be:
select drop_table('foo', 1);
I should also caution that because you have not specified the table_schema field, it's conceivable that your target table exists in another schema, and the actual drop command will fail because it doesn't exist in the default schema.
I have a select statement that is generated dynamically based on the supplied parameter. The problem is that postgresql always says:
argument of WHERE must be type boolean, not type character varying no matter what the parameter is. Did I miss anything?
CREATE OR REPLACE FUNCTION getuid(name character varying) RETURNS integer AS $$
DECLARE
statement varchar;
uid integer;
BEGIN
IF ($1 = '') THEN
statement := 'TRUE';
statement := CAST(statement AS BOOLEAN);
ELSE
statement := 'users.keywords ILIKE''' || '%' || $1 || '%''';
END IF;
SELECT INTO uid id FROM users WHERE "statement";
RETURN uid;
END;
$$ LANGUAGE plpgsql
You need EXECUTE if you want to generate dynamic commands inside a function. You could also use two different sections:
CREATE OR REPLACE FUNCTION getuid(name character varying) RETURNS integer AS $$
DECLARE
statement varchar;
uid integer;
BEGIN
IF ($1 = '' OR $1 IS NULL) THEN -- section 1
SELECT id INTO uid FROM users;
ELSE -- section 2
SELECT id INTO uid FROM users WHERE users.keywords ILIKE '%' || $1 || '%';
END IF;
RETURN uid;
END;
$$ LANGUAGE plpgsql;
EXECUTE is a PL/pgSQL statement and not SQL statement. So you have to wrap your dynamic query into PL/pgSQL stored procedure.
Be careful about variable substitution and do not forget to use quote_literal() or quote_nullable() when building up you query.
Have look in documentation here: http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN