Error in postgresql function - postgresql

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;

Related

Syntax error at or near "Perform" when calling a returns-void function

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 get a syntax error with an INSERT function with Postgres

I try to write an insert function in Postgres, but always get the error that I have a syntax error on line 7.
CREATE FUNCTION "Portfolio"."Einfuegen"(IN "idIN" integer, IN "bildIN" bigint, IN "dokumenteIN"
text[])
RETURNS SETOF "Portfolio"."Namen"
LANGUAGE 'sql'
AS $BODY$
BEGIN
INSERT INTO Portfolio.Namen (_id,dokumente,bild) VALUES (idIN,dokumenteIN,bildIN);
END;
$BODY$;
ALTER FUNCTION "Portfolio"."Einfuegen"(integer, bigint, text[])
OWNER TO postgres;
A language sql function may not use a begin ... end; block. Additionally: your function is declared as returns setof but doesn't return anything.
And once you start using the stupid double quotes around identifiers (and parameters) you have always use them:
So it should look like this:
CREATE FUNCTION "Portfolio"."Einfuegen"(IN "idIN" integer, IN "bildIN" bigint, IN "dokumenteIN" text[])
RETURNS SETOF "Portfolio"."Namen"
LANGUAGE sql
AS
$BODY$
INSERT INTO "Portfolio"."Namen"(_id,dokumente,bild)
VALUES ("idIN", "dokumenteIN", "bildIN") --<< you have to use the quotes here as well
returning *; -- return the newly inserted row
END;
$BODY$;
I would strongly suggest you do not use quoted identifiers. They are much more trouble in the long run than their are worth it.

Custom function: Insert object into table

I have the following function in my postgres database:
create function my_schema.create_my_book(book my_schema.book) returns my_schema.book as $$
declare
v_book my_schema.book;
begin
insert into my_schema.book(title, language) values (book.title, book.language) returning * into v_book;
return v_book;
end;
$$ language plpgsql volatile;
This way I have to type out all the column names (title, language) and values (book.title, book.language). My book table is quite big so this will blow up my code by a lot, and once I add a column I will have to remember to add it to this function too.
Is there a way to directly insert the whole book my_schema.book object?
Yes, here it is. You do not even need plpgsql to do this, plain sql will do (and works faster).
create or replace function my_schema.create_my_book(arg_book my_schema.book)
returns my_schema.book as
$$
insert into my_schema.book select arg_book.* returning *;
$$ language sql volatile;
I changed the argument's name to arg_book in order to avoid possible ambiguity. And since the type of arg_book is my_schema.book this simple code adapts itself to table mutation and continues to work.
To solve the id issue
create or replace function my_schema.create_my_book(arg_book my_schema.book)
returns my_schema.book as
$$
declare
v_book my_schema.book%rowtype;
begin
arg_book.id := nextval('the-id-sequence-name');
insert into my_schema.book select arg_book.* returning * into v_book;
return v_book;
end;
$$ language plpgsql volatile;
which is pretty close to your initial function, just dynamic.

Create a procedure/function that creates new sequence

I need to create a new procedure/function in Postgres that creates a new sequence.
The procedure/function will get the name of the sequence as a variable and creates it.
I tried to follow the documentation but it's not very helpful. This is what I've got so far but it's not working (of course):
CREATE FUNCTION create_seq(text) RETURNS text
AS 'CREATE SEQUENCE $1 START 100;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
ERROR: return type mismatch in a function declared to return text
DETAIL: Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING.
CONTEXT: SQL function "create_seq"```
you need use dynamic SQL like said #a_horse_with_no_name, but you need use the plpgsql language not sql language for the function, for remember return void,example,:
CREATE FUNCTION create_seq_plpgsql(p_seq_name text)
RETURNS void
AS
$$
begin
execute format('CREATE SEQUENCE %I START 100', p_seq_name);
end;
$$
LANGUAGE plpgsql;
You need dynamic SQL for that, parameters can't be used as identifiers.
To properly deal with names that potentially need quoting, it is highly recommended to use the format() function to generate the SQL.
And you need to declare the function as returns void as you don't want to return anything.
CREATE FUNCTION create_seq(p_seq_name, text)
RETURNS void
AS
$$
begin
execute format('CREATE SEQUENCE %I START 100', p_seq_name);
end;
$$
LANGUAGE plpgsql;
If you are on Postgres 11, you could also use a procedure instead of a function for that.

Can't declare variable inside function on PostgreSQL

I am writing function in PostgreSQL but it doesn't allow me to declare variable inside it. Here is the function.
CREATE FUNCTION clean_emp() RETURNS void AS
$func$
DECLARE cnt varchar;
$func$ LANGUAGE SQL;
Error Message
ERROR: syntax error at or near "varchar"
SQL state: 42601
Character: 66
It is not surprise. The language SQL doesn't support variables. You have to use the language plpgsql.
CREATE OR REPLACE FUNCTION clean_emp()
RETURNS void AS $$
DECLARE cnt varchar;
BEGIN
END;
$$ LANGUAGE plpgsql;
See more in documentation http://www.postgresql.org/docs/current/static/plpgsql.html.
PostgreSQL has more languages for writing function. The SQL language is perfect for one line single statement macros. The PLpgSQL is classical native language similar to Oracle's PL/SQL with embedded SQL.