Can't declare variable inside function on PostgreSQL - 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.

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;
$$;

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.

How to run a PostgreSQL function

I am struggling to execute a PostgreSQL function. I am trying to read the documentation on the side but still no use. I am using Toad Extension for eclipse to develop/run the function
So far, this is what I have written
CREATE OR REPLACE FUNCTION dbName.function_name()
RETURNS VOID AS
$BODY$
DECLARE
x_cur CURSOR FOR select * from dbName.x;
x_row RECORD;
BEGIN
OPEN x_cur;
RAISE NOTICE 'Cursor opened';
LOOP
FETCH x_cur INTO x_row;
EXIT WHEN NOT FOUND;
END LOOP;
CLOSE x_cur;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
I executed the script and then ran select dbName.function_name(); in the sql worksheet and I don't see any output.
I remember writing functions on plsqldeveloper was so easy and interactive and i am struggling with PostgreSQL, could you guys help me getting a headstart.
I dont see any problem using pgAdmin.
The function return VOID, but the RAISE NOTICE show the message.
I simplify the function
CREATE OR REPLACE FUNCTION function_name()
RETURNS VOID AS
$BODY$
DECLARE
BEGIN
RAISE NOTICE 'Cursor opened';
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
And execute the function
SELECT function_name();

Error in postgresql function

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;

SQL Functions cannot return type trigger

I'm using PostgreSQL with pgAdmin and I can't get a trigger function to work. However, as far as I am aware, you can return type trigger in PostgreSQL?
CREATE OR REPLACE FUNCTION validate_Cat()
RETURNS TRIGGER AS
$BODY$
BEGIN
-- CODE here
END;
$BODY$
LANGUAGE SQL;
CREATE TRIGGER validate_Cat
AFTER INSERT OR UPDATE ON Category
FOR EACH ROW execute procedure validate_Cat();
SOLVED, had to change language to PLPGSQL