PostgreSQL trigger function using "case when" and "else" - postgresql

I made a code for update trigger. Whenever I update, I want to fill "price" column of table "new_book" with 1000 if "price" is blank, or 5% discount if "price" is not blank. My postsql code is
create function test()
returns trigger
as
$$
declare pr1 numeric ;
begin
case when old.price is null then pr1=1000
else pr1=pr1*0.95 end
end;
return new;
end
$$
language plpgsql;
but if i run this code, PGAdmin shows an error like that
ERROR: syntax error at or near "else"
LINE 8: else pr1=pr1*0.95 end
^
SQL state: 42601
Character: 117
How can I solve this problem?

You want an IF statement. And if you want to change the value that is stored in the table, you need to modify the new record:
create function test()
returns trigger
as
$$
begin
if new.price is null then
new.new_book := 1000;
else
new.new_book := new.price * 0.95
end if;
return new;
end
$$
language plpgsql;
In order for the assignment to actually be persisted, you have to use a BEFORE trigger:
create trigger set_new_book_trigger
before insert or update on the_table
for each row
execute procedure test();

Related

Create fuction in pgplsql has error in if condition

I am trying to create function in postgres
CREATE OR REPLACE FUNCTION cms_inventory_proc()
RETURNS TRIGGER
AS
$BODY$
BEGIN
IF NEW.permanent = 'YES' THEN
INSERT INTO cms_inventory(id, version, scheme_id, register_num, cms_reference, sensor_id)
VALUES (NEW.id, 0, NEW.scheme_id, NEW.register_num, NEW.cms_reference, NEW.sensor_id);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
ERROR: syntax error at or near "IF"
LINE 9: IF NEW.permanent ='YES' THEN
While it is working in online compiler

Why am I getting a syntax error when using an IF statement in my Postgres function?

I am creating a function that allow me to conditionally update specific columns in a table. However, I get an error indicating that there is a syntax error at or near "IF" when I try to run the following code. I'm a bit new to Postgres so it's quite possible. I can't understand some concept/syntax thing in Postgres. Can someone help me by pointing out the mistake I must be making?
CREATE OR REPLACE FUNCTION profiles.do_something(
p_id UUID,
p_condition1 BOOLEAN,
p_condition2 BOOLEAN,
p_condition3 BOOLEAN
)
RETURNS void AS $$
BEGIN
IF p_condition1 IS TRUE THEN
UPDATE tablename SET column1 = null WHERE member_id = p_id;
END IF;
IF p_condition2 IS TRUE THEN
UPDATE tablename SET column2 = null WHERE member_id = p_id;
END IF;
IF p_condition3 IS TRUE THEN
UPDATE tablename SET column3 = null WHERE member_id = p_id;
END IF;
END;
$$ LANGUAGE 'sql';
tl;dr $$ LANGUAGE 'plpgsql'
$$ LANGUAGE 'sql';
^^^^^
You're tell it to parse the body of the function as sql. In SQL, begin is a statement which starts a transaction.
create or replace function test1()
returns void
language sql
as $$
-- In SQL, begin starts a transaction.
-- note the ; to end the statement.
begin;
-- Do some valid SQL.
select 1;
-- In SQL, end ends the transaction.
end;
$$;
In SQL you wrote begin if ... which is a syntax error.
The language you're using is plpgsql. In plpgsql, begin is a keyword which starts a block.
create or replace function test1()
returns void
language plpgsql
as $$
-- In PL/pgSQL, begin starts a block
-- note the lack of ;
begin
-- Do some valid SQL.
select 1;
-- In PL/pgSQL, end ends the block
end;
$$;

Trigger function to update timestamp attribute when any value in the table is updated

I want to update the timestamp attribute 'register_updated' to the current_timestamp whenever any value is updated in the table.
This is my function
CREATE OR REPLACE FUNCTION fn_register_updated()
RETURNS trigger language plpgsql AS $$
BEGIN
UPDATE tb_register
SET register_updated = CURRENT_TIMESTAMP
WHERE (OLD.* IS DISTINCT FROM NEW.*);
RETURN NEW;
END;
$$;
CREATE TRIGGER tg_register_updated
BEFORE UPDATE
ON tb_register
FOR EACH ROW
EXECUTE PROCEDURE fn_register_updated();
But whenever I run an update on a table I receive the following error:
SQL statement "UPDATE tb_register
SET register_updated = CURRENT_TIMESTAMP"
PL/pgSQL function fn_register_updated() line 3 at SQL statement
SQL statement "UPDATE tb_register
SET register_updated = CURRENT_TIMESTAMP"
PL/pgSQL function fn_register_updated() line 3 at SQL statement
SQL statement "UPDATE tb_register
Any ideas on how to solve this?
I am struggling with the use of UPDATE within the body of the function.
Thank you,
Sample code for you:
CREATE OR REPLACE FUNCTION fn_register_updated()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
new.register_updated = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$function$;
create trigger tg_register_updated before
update
on
tb_register for each row execute function fn_register_updated();

postgresql - trigger function with condition

I'm trying to create a trigger with a condition. Based on the geom length I want the attribute "nom" (= name) to be written in upper case or lower case.
here's what I have:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= (ST_Length(new.geom));
if (SELECT dummy FROM ligne_ligne)>100
then NEW.nom:= LOWER(nom) FROM ligne_ligne;
else NEW.nom:= UPPER(nom) FROM ligne_ligne;
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
DROP trigger IF EXISTS test_upper_lower on public.ligne_ligne;
CREATE trigger test_upper_lower BEFORE INSERT OR UPDATE on public.ligne_ligne
FOR EACH ROW
EXECUTE PROCEDURE public.test_upper_lower();
With this I have a "more than one row returned by a subquery" error
Based on other questions on this forum I tried it using case instead of if and using when in the trigger itself not the function but neither are working
Any ideas ?
Thanks
You don't need (or can actually) use SELECT statements to access data from the inserted row.
The part SELECT dummy FROM ligne_ligne returns all rows from that table - not just from the one relevant to the trigger.
As you just want to check the value you just calculated, simply use new.dummy at that point:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= ST_Length(new.geom);
if new.dummy > 100 then --<< no SELECT necessary
NEW.nom:= LOWER(new.nom); --<< no "FROM", just access the value
else
NEW.nom:= UPPER(new.nom);
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

Move/fetch cursor in loop (PostgreSQL)

I need to create trigger to check if new inserted element's id isn't repeated. The problem is in the LOOP statement, console spit out the error:
CONTEXT: SQL statement in PL/PgSQL function "foo" near line 7
LINE 1: move forward 1 from $1
Here is my function:
create function foo() returns trigger as'
declare xyz cursor for select id from accounts;
begin
LOOP
if NEW.id = xyz then
raise notice ''Id is just used!'';
else
move forward 1 from xyz;
end if;
END LOOP;
return NEW;
close xyz;
end;
' language 'plpgsql';
create trigger foo before insert on accounts for each
row execute procedure foo();
Your example has no sense (you can't compare scalar value with cursor). Cursor self is like pointer without any value.
if NEW.id = xyx then
Why you don't do
BEGIN
IF EXISTS(SELECT * FROM accounts a WHERE a.id = NEW.id) THEN
RAISE NOTICE ''Id is used''; -- better RAISE EXCEPTION
END IF;
RETURN NEW;
END;
second nonsense
RETURN NEW;
CLOSE xyz; -- no statement is executed after RETURN