PostgreSQL: How to assign "SELECT" query to variable using dblink? - postgresql

Here I am trying to assign a "SELECT" query to a specific variable. The select query is retrieving rows from other database table using dblink. For example as shown below:
Example: My try
create or replace function fun(names varchar(60), id bigint) returns void as
$$
Declare
sql varchar;
Begin
sql := 'Select * from dblink'('conn','select * from tablex') /* Error occurred here */
'where name = ''' || names ||'''';
raise info '%',sql;
execute sql,'names varchar(60)',names=names;
end;
$$
Language plpgsql;
ERROR: syntax error at or near "("

You've messed up your quotimg.
You can use dollar-quoting inside the fumction too.
sql := $SQL$...$SQL$

Solution: Here is the solution
create or replace function fun(names varchar(60), id bigint) returns void as
$$
Declare
sql varchar;
Begin
sql := 'Select * from dblink(''conn','select * from tablex'')
where name = ''' || names ||'''';
raise info '%',sql;
execute sql,'names varchar(60)',names=names;
end;
$$
Language plpgsql;

Related

Argument not taking the value from Postgres function

I have a simple Postgres function where I want to take table_name as a parameter and pass it into an argument and delete the data from table by condition.
CREATE OR REPLACE FUNCTION cdc.audit_refresh(tablename text)
RETURNS integer AS
$$
BEGIN
delete from tablename where id<4;
RETURN(select 1);
END;
$$ LANGUAGE plpgsql;
select cdc.audit_refresh('cdc.adf_test');
But it throws out an error that tablename
ERROR: relation "tablename" does not exist in the delete statement.(refer snapshot)
What you want to achieve is to execute Dynamic SQL statements. You can do this with EXECUTE. See more here
CREATE OR REPLACE FUNCTION audit_refresh(tablename text)
RETURNS integer AS
$$
DECLARE
stmt TEXT;
BEGIN
stmt = 'delete from '||tablename||' where id<4;';
EXECUTE stmt;
RETURN 1;
END
$$ LANGUAGE plpgsql;

Save execute results into a table

Below is a simplified postgres stored procedure I am trying to run:
create or replace procedure my_schema.tst(suffix varchar)
as $$
begin
execute(' select *
into my_schema.MyTable_'||suffix||'
From my_schema.MyTable
');
end;
$$
language plpgsql;
When I attempt to run using something like:
call my_schema.tst('test');
I get this error Invalid operation: EXECUTE of SELECT ... INTO is not supported;
Is it possible to execute a dynamic query that creates a new table? I have seen examples that look like:
Execute('... some query ...') into Table;
but for my use case I need the resulting tablename to be passed as a variable.
In PostgreSQL you can use INSERT INTO tname SELECT...
create or replace procedure my_schema.tst(suffix varchar)
as $$
begin
execute ' INSERT INTO my_schema.MyTable_'||suffix||' SELECT *
FROM my_schema.MyTable
';
end;
$$
language plpgsql;
or Use CREATE TABLE tname AS SELECT..., :
create or replace procedure my_schema.tst(suffix varchar)
as $$
begin
execute ' CREATE TABLE my_schema.MyTable_'||suffix||' as SELECT *
FROM my_schema.MyTable
';
end;
$$
language plpgsql;

how to handle refcursor not retrieving data in PGSQL

How to handle refcursor not retrieving data(empty resultset) in PGSQL?
create or replace function function_1( In tblname varchar(15))
returns refcursor
language plpgsql
as $$
declare
v_cnt integer;
r_ref refcursor='ref2';
v_sql text='select * from tbl where 1=2';--default statement;shld return empty if
--input is invalid
begin
if tblname ilike 'scientist' then
v_sql:='select * from tbl'; --table name 1
end if;
open r_ref for
execute v_sql;
return r_ref;
end;
$$;
Is there any other way to handle without using dynamic sql?
execution: Test case 1 : should return empty result set
select * from function_1('invalid');
fetch all in "ref2";
execution: Test case 2 : should return proper data from able
select * from function_1('scientist');
fetch all in "ref2";
Thanks
You don't need a dynamic query when you only have one test case to cover = 'scientist'. In this case, you can simply do :
create or replace function function_1( In tblname varchar(15))
returns setof scientist language plpgsql as $$
begin
if tblname ilike 'scientist' then
return query
select * from scientist ;
end if;
end;
$$;

PostgreSQL: ERROR: syntax error at or near "-"

Here I need to call a function with some parameters.
Example:
Function:
create or replace function testfunction(ids int,pcname varchar)
returns void as
$$
declare
sql varchar;
qu varchar := 'tabletemp_';
begin
qu := qu ||ids ||'_'|| pcname;
sql := 'Drop view if exists '||qu;
raise info '%',sql;
execute sql;
end;
$$
language plpgsql;
Calling Function:
select testfunction(1,'abc-pc');
Error:
ERROR: syntax error at or near "-"
Drop view if exists tabletemp_1_abc-pc
^
Question: How can I pass such parameter while calling function?
You forgot to quote_ident.
sql := 'Drop view if exists '|| quote_ident(qu);
but you should preferably use format:
sql := format('Drop view if exists %I', qu || ids ||'_'|| pcname);
Try This:
create or replace function testfunction(ids int,pcname varchar)
returns void as
$$
declare
sql varchar;
qu varchar := 'tabletemp_';
begin
qu := qu ||ids ||'_'|| pcname;
sql := 'Drop view if exists "'||qu||'"';
raise info '%',sql;
execute sql;
end;
$$
language plpgsql;
Here I add double quote around table name.

PostgreSQL: Select string_agg into variable

I have a string to execute with the string aggregate function within the postgresql function. Here is the following script for that.
Example:
create or replace function f(colvalue int,colnvalue varchar)
returns void as
$$
declare
sql varchar;
var varchar;
begin
sql := 'Select var:= string_agg(................) /* Error occurred here near var:= */
from tablename where cola ='|| colvalue || ' AND coln ='|| colnvalue;
raise notice '%'sql;
execute sql into var;
raise notice var;
end;
$$
language plpgsql;
Error:
ERROR: syntax error at or near ":="
Note: I want the result of string_agg into var.
Dynamic SQL can contains SQL statement only - but ":=" is a PL/pgSQL statement. Next, it is clean from your example, so it is useless there. Second issue is a SQL injection vulnerability (still this code should not work). Newer use a patter ' || varcharvar || ' for SQL used in dynamic SQL.
CREATE OR REPLACE FUNCTION f(colvalue int,colnvalue varchar)
RETURNS void AS $$
DECLARE
sql varchar;
var varchar;
BEGIN
sql := 'SELECT string_agg(..) FROM tablename WHERE cola=$1 AND coln=$2';
RAISE NOTICE '%', sql;
EXECUTE sql INTO var USING colvalue, colnvalue;
RAISE NOTICE '%', var;
END;
$$ LANGUAGE plpgsql;