Problem with PostgreSQL function parameters (Converting MySQL Stored Procedures) - sql

I am converting a few simple MySQL stored procedures to PostgreSQL Functions and for some reason when I execute the following function it throws an error when executed.
I created the function with the following code:
CREATE FUNCTION cc.fs_ivr_updatecalltransfer(_ParentContactID
int[11], _CalledID varchar[32])
RETURNS int AS $$
DECLARE
pcID int;
BEGIN
if _ParentContactID<>0 then
update cc.tblcontacts set cc.tblcontacts.transferdest =
_CalledID where cc.tblcontacts.contactid =
_ParentContactID;
end if;
RETURN _ParentContactID;
END;
$$ LANGUAGE plpgsql;
I Execute it manually like this:
SELECT cc.fs_ivr_updatecalltransfer(3,"test")
It throws this error:
SQL error:
ERROR: column "test" does not exist
LINE 1: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
In statement: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
Any Suggestions?

Use single quotes to quote strings, not double quotes. 'test' means the string "test", whereas "test" means the identifier "test", which postgresql tries to resolve as a column, same as using backquotes in MySQL.

Related

Accessing parameters in a SQL stored Procedure in Snowflake

I am trying to create a stored procedure that uses an integer parameter and dateadd() to create a timestamp that's used to filter results in a where clause. I am getting "Uncaught exception of type 'STATEMENT_ERROR' on line 3 at position 2 : SQL compilation error: error line 9 at position 53 invalid identifier 'X_DAYS_BACK'" when I try to run the procedure below. If I move the return line above the create table line the procedure successfully runs and the return string includes the actual value of x_days_back (e.g. base.ITEM updated for last 3 days.).
CREATE OR REPLACE PROCEDURE BASE.ITEM_LOAD_test(X_DAYS_BACK INTEGER)
returns string not null
language SQL
as
$$
BEGIN
CREATE OR REPLACE TEMPORARY TABLE BASE.TEMP_DELTA_ITEM (
ID STRING
)
AS
SELECT
SOURCE||KEY AS ID
FROM BASE.SUPPLIER_CATALOG_ITEM
WHERE
CDP__ETL_UPDATE_TIMESTAMP >= DATEADD(Day ,-1*X_DAYS_BACK, CURRENT_DATE);
drop TABLE BASE.TEMP_DELTA_ITEM;
RETURN 'base.ITEM updated for last ' || X_DAYS_BACK || ' days.' ;
END;
$$
How do I access a parameter of a SQL stored procedure within a function such as dateadd? I know it's a preview feature, so is this not currently implemented or?
Toss a colon in front of the variable/parameter:
DATEADD(day, -1*:X_DAYS_BACK, CURRENT_DATE);
Their documentation isn't amazing for SQL stored procedures but there is mention of this here where it states:
You can use a variable in a SQL statement. (This is sometimes referred to as binding a variable.) Prefix the variable name with a colon.

Postgresql Function execute format dynamic DDL value error

So, i need to make a function that can generate schema & table that schema name and table name depend on parameter send called _schema_name for schema name & _tp_table_name for table name.
My pgsql function code right now :
CREATE OR REPLACE FUNCTION public.addschema(_schema_name character varying, _tp_table_name character varying )
RETURNS character varying
LANGUAGE plpgsql
AS $function$
begin
execute format('CREATE schema %I',_schema_name);
execute format('CREATE TABLE %I.%I( id uuid NOT NULL DEFAULT uuid_generate_v4(),
raw_id uuid NULL)', _schema_name, _tp_table_name);
RETURN _schema_name;
END;
$function$
;
so i run the function with this :
select addschema('newschema','new_tbl');
i've got an error like this :
SQL Error [22023]: ERROR: unrecognized format() type specifier "I"
Hint: For a single "%" use "%%".
Where: PL/pgSQL function addschema(character varying,character varying) line 11 at EXECUTE
anyone have any hints? thank you..
The problem has to be somewhere in the client side. Your function looks just fine. I've tested it (slightly formatted) in psql, pgAdmin4 and DBeaver 21.2.0.202108310918.. all worked just fine:
CREATE OR REPLACE FUNCTION public.addschema(_schema_name text, _tp_table_name text )
RETURNS text
AS $$
BEGIN
EXECUTE format('CREATE SCHEMA %I;',_schema_name);
EXECUTE format('CREATE TABLE %I.%I( id uuid NOT NULL DEFAULT uuid_generate_v4(),
raw_id uuid NULL)', _schema_name, _tp_table_name);
RETURN _schema_name;
END
$$ LANGUAGE plpgsql;
DBeaver screenshot:
Alternatively, you can take look at the database log files to see how the query is actually being sent to the database. Also, in case you're using an older PostgreSQL version, format() is supported only after PostgreSQL 9.6+

Postgresql 11 - Create Procedure to Execute COPY function

I'm currently trying to create a procedure to automatically copy data into my database when I call the procedure. However, every time I call it I get the following error:
ERROR: column "name" does not exist
LINE 1: SELECT format('COPY test(%L) FROM %s CSV HEADER', name, '/Us...
How does the column not exist? Here's everything I've written out:
CREATE PROCEDURE
test_insert() AS
$$
BEGIN
EXECUTE format('COPY test(%L) FROM %s CSV HEADER', name, '/Users/Receiving.csv');
END;
$$ LANGUAGE plpgsql;
If you use name without single quotes, it is interpreted as a column name in the (tacit) SELECT statement
SELECT format('...', name, '...')
that PL/pgSQL runs when you execute your function.
Since this SELECT statement does not have a FROM clause, you get the observed error.
The solution is to use a string literal instead, i.e. write 'name' instead of 'name'.

Why has a query no "destination for result data" in PostgreSQL stored procedure?

I'm new in postgre and I'm with a problem.
I want to great the procedure:
CREATE OR REPLACE FUNCTION autenticarusuario()
RETURNS users AS
$BODY$`
DECLARE
login text;
senha text;
BEGIN
SELECT * FROM users WHERE login_user = login
AND pass_user = senha;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100;
ALTER FUNCTION autenticarusuario()
OWNER TO postgres;
but I always get the message:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function autenticarusuario() line 6 at SQL statement
********** Error **********
ERROR: query has no destination for result data
SQL state: 42601
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Context: PL/pgSQL function autenticarusuario() line 6 at SQL statement
The issue here is that you're telling Postgres "Start executing this function, then execute this query". Postgres is complaining because you don't tell it what to do with the query results. You could either use a SELECT INTO statement, or you could use RETURN QUERY to return a single column, like the user id:
CREATE OR REPLACE FUNCTION autenticarusuario()
RETURNS SETOF INTEGER AS
$BODY$`
DECLARE
login text;
senha text;
BEGIN
RETURN QUERY SELECT id
FROM users
WHERE login_user = login
AND pass_user = senha;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100;
If you want to return multiple fields for each record, you can use a similar strategy to what is detailed here and create your own type.
My colleague faced a similar problem. She than used OPEN MYCURS before the select query and RETURN MYCURS after the select query.

Stored Procedure / Stored Function: SELECT in PostgreSQL

I have created a stored procedure / function with a simple SELECT in PostgreSQL:
CREATE FUNCTION select_proc2()
RETURNS SETOF procedure AS
$DELIMETER$
SELECT * FROM procedure;
$DELIMETER$
LANGUAGE 'sql'
This one works but when I tried to be specific like this:
CREATE FUNCTION select_proc2(INT)
RETURNS SETOF procedure AS
$DELIMETER$
SELECT "Fname" FROM procedure where "Id" = $1;
$DELIMETER$
LANGUAGE 'sql'
it returns an error:
ERROR: return type mismatch in function declared to return procedure
DETAIL: Final statement returns character instead of integer at
column 1. CONTEXT: SQL function "select_proc2"
I tried any solution that I can think of. Anyone here know how to solve this error?
You need to adapt the RETURN type to what's actually returned:
CREATE OR REPLACE FUNCTION select_proc2(int)
RETURNS SETOF text AS
$func$
SELECT "Fname" FROM procedure WHERE "Id" = $1;
$func$ LANGUAGE sql
In your second version you only return one column. From the name I am deriving the data type text, but that's just a guess.
If "Id" is the primary key column of procedure or otherwise defined UNIQUE, only one row can be returned and you can simplify to:
RETURNS text
Also don't quote the language name. sql is an identifier here, not a string literal. It's only tolerated for historic reason, but it's probably going to be an error in future versions.
Concerning your column names: My advise is to use non-quoted lower-case identifiers exclusively in Postgres. Start by reading the chapter "Identifiers and Key Words" to learn about the significance of "id", "Id", ID or id as column name.
remove quotes around field names (without "):
CREATE FUNCTION select_proc2(INT)
RETURNS SETOF procedure AS
$DELIMETER$
SELECT Fname FROM procedure where Id = $1;
$DELIMETER$
LANGUAGE 'sql'