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

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.

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;

Using to_jsonb(NEW) and execute

CREATE OR REPLACE FUNCTION change_trigger() RETURNS trigger AS $$
BEGIN
INSERT INTO static_table_name (content) VALUES (to_jsonb(NEW));
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
↑ is working, but I'd like to have opportunity to send target table name for inserting.
So,
by the code above, I was able to use dymanic_table_name,
CREATE OR REPLACE FUNCTION change_trigger() RETURNS trigger AS $$
DECLARE
dymanic_table_name TEXT;
BEGIN
dymanic_table_name := TG_ARGV[0];
EXECUTE 'INSERT INTO ' || dymanic_table_name || ' (content) VALUES (' || to_json(NEW) || ');';
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
but it fails, when try to insert result of 'to_json' function...
ERROR:
ERROR: "{"またはその近辺で構文エラー
LINE 1: ..._table (content) VALUES ({"id":43,"...
^
※ Sorry for Japanese syntax ( *´艸`)
You'll have to use dynamic SQL like this:
EXECUTE
format(
'INSERT INTO %I (content) VALUES (to_json($1))',
dymanic_table_name
)
USING NEW;

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;

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

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;