POSTGRESQL trigger troubles - postgresql

Wrote this code. Problem with this code is that it's doing nothing. Should update OTB_Name when I'm updating table, but nothing happens.
Can somebody tell me where my problem is?
CREATE OR REPLACE FUNCTION public.demand_lom_ar5_tracker()
RETURNS trigger AS $demand_lom_ar5_tracker$
BEGIN
-- INSERT
IF (TG_OP = 'INSERT') THEN
UPDATE public.demand_lom_ar5
SET "OTB_Name" = ar5_area_otb."OTB_Name"
FROM mapinfo.public.ar5_area_otb
WHERE ST_Contains (mapinfo.public.demand_lom_ar5."SP_GEOMETRY", mapinfo.public.ar5_area_otb."SP_GEOMETRY");
RETURN NULL;
-- UPDATE
ELSIF (TG_OP = 'UPDATE') THEN
UPDATE public.demand_lom_ar5
SET "OTB_Name" = ar5_area_otb."OTB_Name"
FROM mapinfo.public.ar5_area_otb
WHERE NEW."MI_PRINX" = OLD."MI_PRINX" and ST_Contains (mapinfo.public.demand_lom_ar5."SP_GEOMETRY", mapinfo.public.ar5_area_otb."SP_GEOMETRY");
RETURN NULL;
END IF;
END;
$demand_lom_ar5_tracker$ LANGUAGE plpgsql;
--apply the trigger:
DROP TRIGGER IF EXISTS trg_demand_lom_ar5_tracker
ON public.demand_lom_ar5;
CREATE TRIGGER trg_demand_lom_ar5_tracker
AFTER INSERT OR UPDATE ON public.demand_lom_ar5
FOR EACH ROW EXECUTE PROCEDURE public.demand_lom_ar5_tracker();

Related

After update trigger to replace an empty string with null updates all the data in that column to null

I want to update the record of a particular user only. But the update trigger fires for all the users.
CREATE OR REPLACE FUNCTION replace_empty_username_with_null() RETURNS TRIGGER
LANGUAGE plpgsql AS
BEGIN
UPDATE user_temp
SET username=null
WHERE NEW.id = OLD.id and NEW.username = '';
RETURN NEW;
END
CREATE TRIGGER replace_empty_username
AFTER UPDATE OF username ON user_temp
FOR EACH ROW
WHEN (NEW.username = '' AND OLD.id = NEW.id)
EXECUTE PROCEDURE replace_empty_username_with_null();
The expression NEW.id = OLD.id makes sense in the WHEN clause of the trigger ("ID did not change and is not null"). But it makes no sense in the body of the trigger function, where it burns down to TRUE. Also, to only affect the row which is being updated, just use a BEFORE trigger instead:
CREATE OR REPLACE FUNCTION replace_empty_username_with_null()
RETURNS TRIGGER LANGUAGE plpgsql AS
$func$
BEGIN
NEW.username = null; -- !
RETURN NEW;
END
$func$
CREATE TRIGGER replace_empty_username
BEFORE UPDATE OF username ON user_temp -- !
FOR EACH ROW
WHEN (NEW.username = '' AND OLD.id = NEW.id)
EXECUTE PROCEDURE replace_empty_username_with_null();
Related:
PostgreSQL Update trigger

Postgres insert or update trigger WHEN condition (old)

I need write insert or update trigger, but with WHEN condition with compare OLD and NEW rows.
According documentation OLD is null for insert operation. How i can use OLD in WHEN condition for INSERT AND UPDATE triggers?
Example trigger:
CREATE TRIGGER mytrigger
BEFORE INSERT OR UPDATE ON "mytable"
FOR EACH ROW
WHEN (NEW.score > 0 AND OLD.score <> NEW.score)
EXECUTE PROCEDURE mytrigger();
but for insert OLD is null.
Option A:
You can change the code so that conditions will be in the trigger function rather than the trigger itself. With this approach OLD will be used only in the UPDATE.
Trigger:
CREATE TRIGGER mytrigger
BEFORE INSERT OR UPDATE ON "mytable"
FOR EACH ROW
EXECUTE PROCEDURE mytrigger();
Trigger function:
CREATE OR REPLACE FUNCTION mytrigger()
RETURNS trigger AS
$BODY$
begin
if NEW.score > 0 then
--code for Insert
if (TG_OP = 'INSERT') then
YOUR CODE
end if;
--code for update
if (TG_OP = 'UPDATE') then
if OLD.score <> NEW.score then -- (if score can be null see #voytech comment to this post)
YOUR CODE
end if;
end if;
end if;
return new;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
Option B:
As Thilo suggested write two triggers that share the same trigger function.
Triggers:
CREATE TRIGGER mytrigger1
BEFORE INSERT ON "mytable"
FOR EACH ROW
WHEN NEW.score > 0
EXECUTE PROCEDURE mytrigger();
CREATE TRIGGER mytrigger2
BEFORE UPDATE ON "mytable"
FOR EACH ROW
WHEN (NEW.score > 0 AND OLD.score <> NEW.score)
EXECUTE PROCEDURE mytrigger();
Trigger function:
CREATE OR REPLACE FUNCTION mytrigger()
RETURNS trigger AS
$BODY$
begin
YOUR CODE
return new;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
Trigger.oldMap.keySet(); will give the Id's present in the Trigger.oldMap.
It is a set type collection of all the Id's.
have a look at the following example, change the DML events in the trigger events every time and see the debug logs.
you will understand which trigger context variable is available for which DML event.
CREATE TRIGGER Email_Check_On_Contact
before update{
oldMap<ID,Contact>=new Map<ID,Contact>();
o = trigger.oldMap;
for(Contact newcont: trigger.new)
{
if(newcont.Email != o.get(newcont.Id).Email)
{
newcont.Email.addError('Email cannot be changed');
}
}
}

How to apply a update after an inser or update POSTGRESQL Trigger

How to apply an update after an insert or update in POSTGRESQL; I have got a table which has a field lastupdate; I want that field to be set up whenever the row is updated or when it was inserted.
I tried this trigger, but It is not working! HELP!!
CREATE OR REPLACE FUNCTION fn_update_profile()
RETURNS TRIGGER AS $update_profile$
BEGIN
IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE' ) THEN
UPDATE profile SET lastupdate=now() where oid=OLD.oid;
RETURN NULL;
ELSEIF (TG_OP = 'DELETE') THEN
RETURN NULL;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$update_profile$ LANGUAGE plpgsql;
Your trigger function can be a lot easier than you had. Keep in mind that PG will do the update or the insert on the original table, you only have to deal with keeping the profile table up-to-date:
CREATE OR REPLACE FUNCTION fn_update_profile()
RETURNS TRIGGER AS $update_profile$
BEGIN
UPDATE profile SET lastupdate = now() WHERE oid = NEW.oid;
RETURN NEW;
END;
$update_profile$ LANGUAGE plpgsql;
The INSERT and UPDATE trigger functions both use the NEW parameter; the INSERT trigger function does not have the OLD parameter. You should always return NEW from the trigger function if successful (or OLD from a DELETE trigger), even if it is an AFTER INSERT OR UPDATE trigger; the whole operation will be rolled back if NULL is returned. If you then define the actual trigger to fire after the insert or update, you should be good:
CREATE TRIGGER tr_update_profile
AFTER INSERT OR UPDATE ON my_table
FOR EACH ROW EXECUTE PROCEDURE fn_update_profile();

How to create a trigger that checks values?

I need help with my trigger. For example i have Query like this
INSERT INTO test(id_users,id_type,id_color) VALUES(1,3,4);
in my data base i have table with name: test
ghost, id, id_users, id_type, id_color
and i need before insert or update to check
Create trigger
Begin
select id from test where ghost = false and id_users = 26 and id_type = 3
if NO execute INSERT
if YEST exit with no action
END
How can i creat this trigger ?
There are two ways, depending on how you want to manage the problem.
If you wish to silence it, use a before trigger and return null:
create function ignore_invalid_row() returns trigger as $$
begin
if not exists(
select 1
from test
where not ghost
and id_users = new.id_users
and id_type = new.id_type
)
then
return null;
end if;
return new;
end;
$$ language plpgsql;
create trigger ignore_invalid_row_tg before insert on test
for each row execute procedure ignore_invalid_row();
If you wish to raise it, use a constraint trigger and raise an exception:
create function reject_invalid_row() returns trigger as $$
begin
if not exists(
select 1
from test
where not ghost
and id_users = new.id_users
and id_type = new.id_type
)
then
raise exception 'message';
end if;
return null;
end;
$$ language plpgsql;
create constraint trigger reject_invalid_row_tg after insert on test
for each row execute procedure reject_invalid_row();
http://www.postgresql.org/docs/current/static/sql-createtrigger.html
First, you need to create a trigger function and then the trigger, based on it:
CREATE OR REPLACE FUNCTION my_trigger_function() RETURNS TRIGGER AS $BODY$ BEGIN
IF EXISTS (SELECT id FROM test WHERE ghost = false AND id_users = 26 AND id_type = 3) THEN
return NEW;
ELSE
return NULL;
END IF; END; $BODY$ LANGUAGE 'plpgsql';
Then, you create trigger based on this function:
CREATE TRIGGER t_my_trigger BEFORE INSERT ON test FOR EACH ROW EXECUTE PROCEDURE my_trigger_function();
For more on triggers, see postgres docs.

postgresql-using trigger to fire

I want to create a trigger so that whenever I make a change (Update or Delete) it should copy the old data to a new table (with same template).
I tried this code:
create table restrictions(ID int,name text);
insert into restrictions values(122,'suresh');
select * from restrictions;
create table restrictions_deleted(ID int,name text);// this is my duplicate table for keeping information of all updations.
CREATE OR REPLACE FUNCTION moveDeleted() RETURNS trigger AS $$
BEGIN
INSERT INTO restrictions_deleted VALUES(OLD.ID, OLD.name);
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER moveDeleted
BEFORE DELETE ON restrictions
FOR EACH ROW
EXECUTE PROCEDURE moveDeleted();
delete from restrictions where ID=122;
select * from restrictions_deleted;
This code is capable of recording all the deleted data into duplicate table. But I want to do same for updates also.
Any suggestion, any idea?
First - in a trigger function you need to RETURN NEW; instead of RETURN OLD;.
Second - change the trigger to BEFORE DELETE OR UPDATE.
Last - it is better to have AFTER DELETE OR UPDATE for a logging trigger. This way it wont do useless work, when the change is rolled back.
BTW here is a good example of logging/audit trigger.
UPDATE:
The function will look like:
CREATE OR REPLACE FUNCTION moveDeleted() RETURNS trigger AS $$
BEGIN
IF (TG_OP = 'UPDATE') THEN
INSERT INTO restrictions_deleted VALUES(OLD.ID, OLD.name);
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
INSERT INTO restrictions_deleted VALUES(OLD.ID, OLD.name);
RETURN OLD;
END IF;
END;
$$ LANGUAGE plpgsql;