Postgresql Function execute format dynamic DDL value error - sql

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+

Related

Procedure (unknown) does not exist PostgreSQL

I'm new to PostgreSQL, and trying to learn about stored procedure with PostgreSQL. Here are the steps I followed.
Installed pgAdmin4
Created the Database
Created the table "Users" under public schema
Created the procedure "GetUserByEmail"
CREATE OR REPLACE PROCEDURE GetUserByEmail
(
Email Varchar(100)
)
LANGUAGE plpgsql AS
$$
BEGIN
Select * from public."Users" where "Email" = Email
END
$$;
When calling it from query tool, I get an error.
CALL public.GetUserByEmail('d#d.com')
ERROR: procedure public.getuserbyemail(unknown) does not exist LINE
1: CALL public.GetUserByEmail('d#d.com')
^ HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. SQL state: 42883
Character: 6
Checked the permission, and the user has execution rights.
Tried different ways but not sure what is wrong.
Are PostgreSQL column names case-sensitive?
if you create table "users"(a int...) then you stick with "users" every time you select/update/delete "users" table.
You can easily imitate 38.5.9. SQL Functions Returning Sets(https://www.postgresql.org/docs/current/xfunc-sql.html)
CREATE FUNCTION getusers(text) RETURNS SETOF "users" AS $$
SELECT * FROM "users" WHERE email = $1;
$$ LANGUAGE SQL;
SELECT * FROM getusers('hi') AS t1;
stored procedure versus function
demo

How to pass variable from PL/pgSQL function to a query select statement?

CREATE OR REPLACE FUNCTION data_of(_tbl_type anyelement, _missing_id TEXT)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('
SELECT *
from logs
where json_col_a::text like '%$1%' or -- <---- faulty
json_col_b::text like '%$1%' --- <----- faulty
order by timestamp desc'
, pg_typeof(_tbl_type))
USING _missing_id;
END
$func$ LANGUAGE plpgsql;
CREATE TABLE new_table AS TABLE logs WITH NO DATA;
SELECT * FROM data_of(NULL::new_table, '00000000-0000-0000-0000-000000000001');
Adapted from the answer here, I want to pass a GUID as a text into the SELECT query.
I convert the json_col_a, json_col_b from json to text.
Then, I check whether the _missing_id text is found in both columns above.
When I run, I got an error message saying:
ERROR: operator does not exist: unknown % new_table
LINE 4: where diagnostics_context::text like '%$1%' or
What have I missed?
Thanks

Return a table using SQL Procedure?

I have problem with return table using SQL Procedure.
My code:
CREATE PROCEDURE return_data(surname character varying)
LANGUAGE SQL
AS $$
SELECT * FROM peopple WHERE surname=surname
$$;
CALL return_data('Jobs');
Currently the procedure executes without error but it doesn't return a table.
Procedures aren't meant to return anything. Use a set returning function
create function return_data(p_surname varchar)
returns setof people
as
$$
select *
from people
where surname = p_surname;
$$
language sql;
You should also avoid parameter or variable names that have the same name as a column.
Then use it like this:
select *
from return_data('Jobs');
You can append one or more rows to the result set:
CREATE OR REPLACE FUNCTION return_data(surname character varying)
RETURNS TABLE(firstname character varying, surname character varying, age integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT firstname, surname, age
FROM users;
END;
$function$
;
Invoke the function:
SELECT * FROM return_data("a surname");
A function can return but a procedure cannot. Thats true, I wanna add to that we generally use function to return values of one type (in general one value)
While,
Procedure never returns but can behave like a function without a return statement using OUT parameters. To add to this we use procedure when we dont wanna return in actual but executing sql statements but in case if we require a procedure to give multiple values we can make procedure behave like a function for multole values output vja OUT.
As a table can be accessed by record or array type depending upon homogenity. Therefore, use function with return type as record/array.
Hence, as function is solely used to return single output we have to specify via return.

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'

Problem with PostgreSQL function parameters (Converting MySQL Stored Procedures)

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.