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
Related
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+
I am trying to test my stored procedure in MySQL workbench/j. I get an error when I am trying to call the stored procedure.
I have created a table to store the result of my stored procedure
CREATE TABLE IF NOT EXISTS ableok
(
name VARCHAR(50) ENCODE lzo
);
This is my stored procedure:
CREATE OR REPLACE PROCEDURE sp_GetDistSchema()
AS '
BEGIN
SELECT table_schema INTO ableok FROM information_schema.tables;
END;
'
LANGUAGE plpgsql;
This is how i call my stored procedure in SQL workbench/j:
call sp_getdistschema();
Result:
An error occurred when executing the SQL command:
call sp_getdistschema()
[Amazon](500310) Invalid operation: Column "table_schema" has unsupported type "information_schema.sql_identifier".; [SQL State=0A000, DB Errorcode=500310]
1 statement failed.
The SELECT ... INTO structure is used to store a query result into variables. It looks as though you are really just trying to populate the distTable directly. Try this instead:
Update: When processing the information schema in Redshift/PostgreSQL, you apparently need to convert the column datatypes using CAST:
CREATE OR REPLACE PROCEDURE sp_GetDistSchema()
BEGIN
INSERT INTO distTable SELECT DISTINCT CAST(table_schema AS VARCHAR) FROM information_schema.tables;
END;
As #user9601310 mentioned (up voted), you need to CAST the column data types.
I was scratching my head too, even in plain old Postgres when your using the information_schema.
This will 'describe' a table or a view, but won't work unless the query columns are cast as VARCHAR:
CREATE OR REPLACE FUNCTION public.fn_desc(p_tablename VARCHAR)
RETURNS TABLE(vtable_name VARCHAR, vcolumn_name VARCHAR, vdata_type VARCHAR)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT
table_name::VARCHAR,
column_name::VARCHAR,
data_type::VARCHAR
FROM
information_schema.columns
WHERE
table_name ILIKE p_tablename;
END;
$function$
SELECT * FROM public.fn_desc('any_table_or_view');
I'm looking for a way to create a function that takes in two parameters for user name and password and creates a read only role with it. I've tried something like:
create or replace function create_user_readonly (
unm varchar,
pwd varchar
)
returns varchar(10) as $$
begin
create role unm login password #pwd;
return 'success';
end;
$$ language plpgsql;
This throws the error:
[42601] ERROR: syntax error at or near "#" Position: 151
I thought of using dynamic SQL to construct the query but ran into this here (https://www.postgresql.org/docs/9.1/static/plpgsql-statements.html):
Another restriction on parameter symbols is that they only work in
SELECT, INSERT, UPDATE, and DELETE commands. In other statement types
(generically called utility statements), you must insert values textually
even if they are just data values.
here is an example:
create or replace function create_user_readonly (
unm varchar,
pwd varchar
)
returns varchar(10) as $$
begin
execute format($f$create role %I login password '%s'$f$,unm,pwd);
execute format('alter role %I set transaction_read_only to on',unm);
return 'success';
end;
$$ language plpgsql;
keep in mind though you will need to alter user to set transaction_read_only also to make it read only.
also:
CREATE ROLE does not offer setting RO default to role.
ALTER ROLE does
And keep in mind that overcoming uset configuration transaction_read_only is as easy as running one statement.
and create role won't give CONNECT permission, use CREATE USER instead if you want one.
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.
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'