Why I get the following error:
psql:q.sql:22: ERROR: syntax error at or near "IF"
LINE 4: IF id IS NOT NULL THEN
^
psql:q.sql:23: WARNING: there is no transaction in progress
COMMIT
from:
CREATE PROCEDURE my_procedure(id integer)
LANGUAGE SQL
BEGIN ATOMIC
IF id IS NOT NULL THEN
END IF;
END;
But if I remove the IF-THEN statement everything is fine.
My attempt:
I found the correct syntax by creating a new procedure using DBeaver which actually mentioned here:
CREATE OR REPLACE PROCEDURE my_procedure()
LANGUAGE plpgsql
AS $procedure$
BEGIN
END;
$procedure$
Now the problem is there is no syntax highlighting for plpgsql :(
Related
I am new to POSTGRES and currently exploring how to create and execute stored procedures. I was trying a simple example with conditional constructs and got stuck with an error :(
create procedure learnpostgre(x integer, y integer)
language plpgsql
as $$
if x > y
then
raise 'X is greater'
end if
$$;
The error I am getting is 'syntax error at or near if'. I saw similar issues on SO and tried wrapping my code block under do block but faced the same error message for 'Do'. I am running my code in pgadmin4 and postgres version is 14.X
You're missing begin and end and a few semicolons. This should work:
create procedure learnpostgre(x integer, y integer)
language plpgsql
as $$
begin
if x > y
then
raise 'X is greater';
end if;
end
$$
I need to re-create a group of functions but I don't want to check their parameters to use drop if there are functions with the same names but different parameters.
Is this possible to drop/recreate them only by name?
Or is this possible to catch exceptions, raise errors and continue to execute the transaction?
I'm trying to do it using
DO $$
BEGIN
BEGIN
CREATE OR REPLACE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN duplicate_function THEN RAISE NOTICE 'already exists';
END;
END;
$$;
But It completes scripts quietly and does not raise any errors.
You are correct in that 42723 is raised when a named object already, However, it is not a named exception. Thus your exception handles does not recognized, so it takes no action. You can get what you want by directly referencing the SQLSTATE and your error code.
DO $$
BEGIN
BEGIN
CREATE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN SQLSTATE '42723' THEN RAISE NOTICE 'already exists';
END;
END;
$$;
Raise notice sends the text following to sysout, which is often not accessible in a production system. You might want to change to raise exception.
Function
create function public.perform1(myid integer)
returns void
language 'plpgsql'
volatile security definer
as $$
begin
delete from tbl where tblid=myid;
end;
$$;
Got error when calling PERFORM in both pgAdmin and SQL Shell:
perform public.perform1(123);
ERROR: syntax error at or near "perform"
LINE 1: perform public.perform1(123)
^
SQL state: 42601
Character: 1
SELECT public.perform1(123); no good either:
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 perform1(integer) line 3 at SQL statement
SQL state: 42601
perform is only used inside plpgsql. You want:
select public.perform1(123);
Update:
Inside the function is where you need the perform. I mentioned it then forgot to show it:
create function public.perform1(myid integer)
returns void
language 'plpgsql'
volatile security definer
as $$
begin
perform delete from tbl where tblid=myid;
end;
$$;
Update 2:
Well this is will teach me to actually test code. Tested code that works:
create function public.perform1(myid integer)
returns void
language 'plpgsql'
volatile security definer
as $$
begin
delete from tbl where tblid=myid;
end;
$$;
I am using Postgres version 13.1. I want to have a single file where I could store all stored procedures and create them in one shot. But when I put multiple stored procedures in a single file, I get the following error. What am I missing?
In my test.sql file I have the following content:
create or replace procedure tmp1(
)
language plpgsql as
$$
declare
l_count integer;
begin
select 1 into l_count;
raise info 'count: %', l_count;
end;
$$
create or replace procedure tmp2(
)
language plpgsql as
$$
declare
l_count integer;
begin
select 1 into l_count;
raise info 'count: %', l_count;
end;
$$
If I only have the first procedure it gets created and I can call it successfully. But the moment I have the second identical procedure with a different name, it gives me an error as follows (when run from psql):
psql=> \i test.sql
psql:test.sql:23: ERROR: syntax error at or near "create"
LINE 12: create or replace procedure tmp2(
OK - right after posting I tried putting a ";" after the end of first procedure and it works
Explain me please, why I'm getting error here:
djabase=# CREATE or REPLACE FUNCTION upset(domain_name varchar)
RETURNS TABLE (id int, domain varchar(50)) AS $$
BEGIN
SELECT domain from separser_domains where domain=$1;
EXCEPTION
when sqlstate 'no_data' then
INSERT into separser_domains(domain) VALUES (domain_name);
END; $$
LANGUAGE 'sql' STABLE;
ERROR: syntax error at or near "SELECT"
LINE 4: SELECT domain from separser_domains where domain=$1;
You are using PLPGSQL syntax but declaring the function as SQL. This the reason, why the function fails with a SYNTAX ERROR. The language of the function is declared with the statement LANGUAGE and you declared it in the last line:
LANGUAGE 'sql' STABLE;
SQL functions do not support the BEGIN - END statement and exceptions trapping.
To fix it, simple change LANGUAGE 'sql' in LANGUAGE 'plpgsql'.
Some other considerations:
Catching a exception in this place is probably not necessary. Use the FOUND variable instead.
With the STABLE keyword, the function can not perform INSERT. Change STABLEto VOLATILE.
You declared RETURNS TABLE but the function does not return anything. Use RETURNS VOID instead.
Using SELECT and discarding the result is not allowed. Use PERFORM instead.
A valid version of your version could be this:
DROP FUNCTION IF EXISTS upset(varchar);
CREATE or REPLACE FUNCTION upset(domain_name varchar)
RETURNS VOID AS $$
BEGIN
PERFORM domain from separser_domains where domain=domain_name;
IF NOT FOUND THEN
INSERT into separser_domains(domain) VALUES (domain_name);
END IF;
RETURN;
END;
$$
LANGUAGE 'plpgsql' VOLATILE;