plpgsql syntx error at $$ - sql

I'm trying to write a function with plpgsql for some reason i'm getting a syntax error at $$ language plpgsql;
This is the func i'm writing:
create or replace function hello() returns trigger as $$
begin
if new.my_sc!= null and new.his_sc!= null
then update people p
set p.score=p.score+1
where p.id = new.id;
end if;
return null;
$$ language plpgsql;
my Trigger:
after insert on game
execute procedure hello();
my syntax error comes in at the last line.
any idea?
Thankx

Related

ERROR: syntax error at or near "NEW" Position: 179

object: public.fn_set_now_as_updated_at | type: FUNCTION --
-- DROP FUNCTION IF EXISTS public.fn_set_now_as_updated_at() CASCADE;
CREATE FUNCTION public.fn_set_now_as_updated_at ()
RETURNS trigger
LANGUAGE plpgsql
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
PARALLEL UNSAFE
COST 1
AS $$
NEW.updated_at = NOW();
RETURN NEW;
$$;
looks like you forgot to add begin an end clause documentation
CREATE FUNCTION public.fn_set_now_as_updated_at ()
RETURNS trigger
LANGUAGE plpgsql
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
PARALLEL UNSAFE
COST 1
AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$;

How to return the value of function 2 from within function 1

How would I return the return value of a function from within a function (eg. foo() calls
bar())?
create or replace function bar ()
returns text
as $$
begin
select md5(random()::text);
end
$$ language 'plpgsql';
create or replace function foo ()
returns text
as $$
begin
return select bar ();
end
$$ language 'plpgsql';
I keep getting errors like query has no destination for result data
You need to provide something to accept the output of the query:
CREATE OR REPLACE FUNCTION public.bar()
RETURNS text
LANGUAGE plpgsql
AS $function$
declare
md5_val text;
begin
select into md5_val md5(random()::text);
return md5_val;
end
$function$
;
create or replace function foo ()
returns text
as $$
declare
md5_val2 text;
begin
select into md5_val2 bar();
return md5_val2;
end
$$ language 'plpgsql';
select * from foo();
foo
----------------------------------
ac6a4910fac3472d226dc54bb147336e
See:
https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
Both of your functions are some impermissible mixture of 'plpgsql' language and 'sql' language functions. Also, it isn't about calling one from the other, bar() is broken even if you just call it directly, and once fixed then foo() is broken independently of bar() being broken.
Nothing here needs to be in plpgsql, so the simplest repair is just to turn them into 'sql' language functions.
create or replace function bar ()
returns text
as $$
select md5(random()::text);
$$ language 'sql';
create or replace function foo ()
returns text
as $$
select bar();
$$ language 'sql';
If you want them to be plpgsql, then in first case you need to return something, it doesn't just automatically return the result of the last query like SQL language functions do. And in the second one, "return select" is not valid. You could select into a scratch variable and then return that scratch variable, but it easier just to change the "select" to "return" in the first, and remove the wayward "select" in the second.
create or replace function bar ()
returns text
as $$
begin
return md5(random()::text);
end
$$ language 'plpgsql';
create or replace function foo ()
returns text
as $$
begin
return bar();
end
$$ language 'plpgsql';

Conditionally drop an insert in a before insert trigger without returning error

I have the following function in a before insert trigger:
CREATE OR REPLACE FUNCTION schema.table_somefun()
RETURNS trigger AS
LANGUAGE 'plpgsql';
$BODY$
BEGIN
IF NEW.col2 NOT NULL THEN
NEW.col1 := CASE NEW.col1
WHEN '121432' THEN '321123'
ELSE <command> END CASE; --there should be a command aborting insertion without error or exception
END IF;
RETURN NEW;
END;
$BODY$
The ELSE statement should abort insertion. Is there a command which drops the query without telling it to the client and leaving the table untouched?
Just use
RETURN NULL;
instead of
RETURN NEW;
to cancel the INSERT for the row and do nothing instead.
But you cannot execute a PL/pgSQL statement inside an SQL CASE expression. (Don't confuse SQL CASE with the similar control structure CASE of PL/pgSQL!)
Could look like this:
CREATE OR REPLACE FUNCTION schema.table_somefun()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col2 NOT NULL THEN
IF NEW.col1 = '121432' THEN -- could also be plpgsql CASE ...
NEW.col1 := '321123';
ELSE
RETURN NULL;
END IF;
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;

Execute a query for every row of a table inside a trigger function

I have made the following query which is working perfect by itself but when i call it inside trigger function i got problem.
select insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), s.code)
FROM "student" as s
where find_st(s.grade)>=5;
insert_new_grade is a function that inserts a new row in a table every time it's being called.
Here is the trigger :
CREATE OR REPLACE FUNCTION insert_d()
RETURNS TRIGGER AS $$
BEGIN
select insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), s.code)
FROM "student" as s
where find_st(s.grade)>=5;
return new;
END;
$$ LANGUAGE plpgsql;
and here is the insert function :
CREATE OR REPLACE FUNCTION insert_new_grade(title0 character(100), prof0 character(11), prof1 character(11))
RETURNS VOID AS $$
BEGIN
INSERT INTO "d_table"(thes0, title, grade, prof, secProf)
VALUES (null, title0, null, prof0, prof1);
END
$$
LANGUAGE 'plpgsql';
Is there a way to make the query work inside the trigger function ? If i use perform instead of select the insert function does not have result. I've read about cursors but I'm new in postgresql and I don't know how to do it. Any help ?
i modifited your trigger function:
check your trigger function in conlose pgAdmin, is visible raise info text
CREATE OR REPLACE FUNCTION insert_d()
RETURNS TRIGGER AS $$
declare
rec record;
BEGIN
for rec in (select * from student s where find_st(s.grade)>=5) loop
raise info 'LOOP code = %',rec.code;
PERFORM insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), rec.code);
end loop;
return new;
END;
$$ LANGUAGE plpgsql;

plpgsql function. How to compare value to set of values?

I have a trigger function.
I wish to check if an status is one of (5,6,4,7)
CREATE OR REPLACE FUNCTION a()
RETURNS trigger AS
$BODY$
begin
if old.status = (5,6,4,7) then
do something.
end if;
return old;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
how do I change it to proper syntax?
Use IN operator:
...
if old.status IN (5,6,4,7) then
do something.
end if;
...
This is reference of this link.
It only work with postgresql 9.x
CREATE OR REPLACE FUNCTION a()
RETURNS trigger AS
$BODY$
begin
if old.status = ANY (VALUES (5),(6),(4),(7))) then
do something.
end if;
return old;
end;
$BODY$
LANGUAGE plpgsql VOLATILE