update column date to today if any value is modified - sql

I need to modify the column last_update_date to today's date only if any other value of the table Table1 is modified.
The code throws an error if the value to be modified is the column last_update_date.
Here is my code:
CREATE FUNCTION date_change() RETURNS TRIGGER AS $date$
BEGIN
IF (TG_OP = 'UPDATE') THEN
UPDATE erp.tb_customer SET last_update_date = current_date;
ELSIF (OLD.last_update_date != NEW.last_update_date) THEN
RAISE EXCEPTION 'Error not possible to modify the date';
END IF;

There are some problems.
you need a trigger
postgres thows an error when you send your code.
the Syntax can look like you see below
CREATE tABLE erp(myid int , last_update_date timestamp)
CREATE FUNCTION date_change() RETURNS TRIGGER AS $date$
BEGIN
IF (TG_OP = 'UPDATE') THEN
NEW.last_update_date = current_date;
ELSIF (OLD.last_update_date != NEW.last_update_date) THEN
RAISE EXCEPTION 'Error not possible to modify the date';
END IF;
END;
$date$ language 'plpgsql';
CREATE TRIGGER erp_audit
BEFORE UPDATE ON erp
FOR EACH ROW EXECUTE FUNCTION date_change();
db<>fiddle here
As INSTEAD OF TRIGGER, it would look like, but that s for much more extensive functionality
CREATE tABLE erp(myid int , last_update_date timestamp)
CREATE VIEW erp_view AS SELECT * FROM erp;
CREATE FUNCTION date_change() RETURNS TRIGGER AS $date$
BEGIN
IF (TG_OP = 'UPDATE') THEN
NEW.last_update_date = current_date;
ELSIF (OLD.last_update_date != NEW.last_update_date) THEN
RAISE EXCEPTION 'Error not possible to modify the date';
END IF;
END;
$date$ language 'plpgsql';
CREATE TRIGGER emp_audit
INSTEAD OF UPDATE ON erp_view
FOR EACH ROW EXECUTE FUNCTION date_change();
db<>fiddle here

Related

Update columns for the first user inserted

I'm trying to create a trigger and a function to update some columns (roles and is_verified) for the first user created. Here is my function :
CREATE OR REPLACE FUNCTION public.first_user()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
begin
if(select count(*) from public.user = 1) then
update new set new.is_verified = true and new.roles = ["ROLE_USER", "ROLE_ADMIN"]
end if;
return new;
end;
$function$
;
and my trigger :
create trigger first_user
before insert
on
public.user for each row execute function first_user()
I'm working on Dbeaver and Dbeaver won't persist my function because of a syntax error near the "=". Any idea ?
Quite a few things are wrong in your trigger function. Here it is revised w/o changing your business logic.
However this will affect the second user, not the first. Probably you shall compare the count to 0. Then the condition shall be if not exists (select from public.user) then
CREATE OR REPLACE FUNCTION public.first_user()
RETURNS trigger LANGUAGE plpgsql AS
$function$
begin
if ((select count(*) from public.user) = 1) then
-- probably if not exists (select from public.user) then
new.is_verified := true;
new.roles := array['ROLE_USER', 'ROLE_ADMIN'];
end if;
return new;
end;
$function$;

PostgreSQL trigger not executing after update [duplicate]

Here is my trigger function
CREATE OR REPLACE FUNCTION test_table_insert()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.id IS NULL THEN
RAISE EXCEPTION 'id is null';
END IF;
UPDATE e_sub_agreement SET ro_id = NEW.id WHERE id = NEW.id;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER test_table_insert AFTER INSERT ON e_sub_agreement FOR EACH ROW EXECUTE PROCEDURE test_table_insert();
The problem is that it doesn't update table e_sub_agreement. I checked NEW value and everything is good. It returns with the new id. If I change where statement id = "some existing id in table", then it works. It changes ro_id to the new id. How is it possible? My guess is that data has not been inserted into table and trigger function can't find row with the given id. But it's not how trigger's after insert function works. What's the magic?
An AFTER trigger can not change anything. Running an additional UPDATE is also quite inefficient. Change this to a BEFORE trigger and assign the value you want:
CREATE OR REPLACE FUNCTION test_table_insert()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.id IS NULL THEN
RAISE EXCEPTION 'id is null';
END IF;
NEW.ro_id := NEW.id;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER test_table_insert
BEFORE INSERT ON e_sub_agreement
FOR EACH ROW EXECUTE PROCEDURE test_table_insert();
Note that the NOT NULL check is better done by defining the column as NOT NULL.

Rollback trigger on insertion conflict

I had this :
CREATE FUNCTION upsert_user(u_name text, u_fullname text, u_email text, u_suffix text) RETURNS integer
LANGUAGE plpgsql
AS $$
DECLARE
userid users.id_user%TYPE;
BEGIN
LOOP
-- first try to update
UPDATE users SET "fullname" = u_fullname, "email" = u_email, "suffix" = u_suffix WHERE "name" = u_name RETURNING "id_user" INTO userid;
-- check if the row is found
IF FOUND THEN
RETURN userid;
END IF;
-- not found so insert the row
BEGIN
INSERT INTO users ("name", "fullname", "email", "suffix") VALUES (u_name, u_fullname, u_email, u_suffix) RETURNING "id_user" INTO userid;
RETURN userid;
EXCEPTION WHEN unique_violation THEN
-- do nothing and loop
END;
END LOOP;
END;
$$;
CREATE TRIGGER link_entity
BEFORE INSERT
ON public.users
FOR EACH ROW
EXECUTE PROCEDURE public.link_entity();
CREATE FUNCTION link_entity() RETURNS trigger
LANGUAGE plpgsql
AS $$ DECLARE
entityid integer;
BEGIN
INSERT INTO privileges_entities (name) VALUES (NEW.name) RETURNING privileges_entities.id_entity INTO entityid;
IF NOT FOUND THEN
RETURN NULL;
END IF;
NEW.ref_entity := entityid;
RETURN NEW;
END;
$$;
After updated postgresql to version 9.5, I modified the function upsert_user to use the new instruction ON CONFLICT:
CREATE FUNCTION upsert_user(u_name text, u_fullname text, u_email text, u_suffix text) RETURNS integer
LANGUAGE sql
AS $$
INSERT INTO users (name, fullname, email, suffix)
VALUES (u_name, u_fullname, u_email, u_suffix)
ON CONFLICT (name) DO UPDATE SET name=EXCLUDED.name, fullname=EXCLUDED.fullname, email=EXCLUDED.email, suffix=EXCLUDED.suffix
RETURNING id_user;
$$;
The problem is that, now, new rows are inserted in the privileges_entities table even if insertion into the users table fails.
Is it possible to rollback the trigger if the insertion of the user leads to a conflict?
This is indeed a side-effect of using the new ON CONFLICT clause.
My solution here would be to add a check into the link_entity() function itself and prevent it from continuing if the user already exists. Like this:
CREATE FUNCTION link_entity() RETURNS trigger
LANGUAGE plpgsql
AS $$ DECLARE
entityid integer;
nameExists boolean;
BEGIN
EXECUTE format('SELECT EXISTS(SELECT 1 FROM %I.%I WHERE name = NEW.name)', TG_TABLE_SCHEMA, TG_TABLE_NAME) INTO nameExists;
IF nameExists THEN
RETURN NEW; -- just return, entity already linked
END IF;
INSERT INTO privileges_entities (name) VALUES (NEW.name) RETURNING privileges_entities.id_entity INTO entityid;
IF NOT FOUND THEN
RETURN NULL;
END IF;
NEW.ref_entity := entityid;
RETURN NEW;
END;
$$;

Update trigger not firing in plpgsql

I have an update trigger and insert trigger on a table nums with two columns namely name,number.Whenever data is updated or inserted then these triggers are executed.
CREATE OR REPLACE FUNCTION add_log()
RETURNS trigger AS
$BODY$
DECLARE
account_type varchar;
BEGIN
IF (TG_OP = 'INSERT') THEN
INSERT INTO log
VALUES(
now(),
'inserted data is name : '||NEW.name||' num : '||NEW.number
);
RETURN NEW;
ELSEIF (TG_OP = 'update') THEN
INSERT INTO log VALUES
(
now(),
'updated record with old num :'||OLD.number||' with new num : '||NEW.number
);
RETURN OLD;
END IF;
RETURN null;
END;
$BODY$
LANGUAGE plpgsql
creating trigger:
CREATE TRIGGER add_log_trigger
AFTER INSERT OR UPDATE
ON nums
FOR EACH ROW
EXECUTE PROCEDURE add_log();
When an insert operation is performed, insert trigger is being fired.But when update operation is performed no update trigger is being fired.Why?
String comparison is case-sensitive in Postgres. Try TG_OP = 'UPDATE' instead of TG_OP = 'update'.

create a trigger before insert

I want to create a trigger before insert and check inside the trigger function the summary_id values of the new row to be inserted, to see if the summary_id already exists in the table. if it exists then the trigger should return null as I don't want to insert duplicate values. I have written this function, but, when I tried to add a new duplicate row, it was inserted successfully!
CREATE OR REPLACE FUNCTION trigger_ack_bi()
RETURNS trigger AS $$
--DECLARE
-- max_points INTEGER;
BEGIN
IF(TG_OP = 'INSERT') THEN
IF NEW.ack_summary_id = (SELECT ack_summary_id FROM scm_main.tbl_ack WHERE scm_main.tbl_ack.ack_summary_id = NEW.ack_summary_id LIMIT 1) THEN
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END IF;
END;
$$LANGUAGE plpgsql;
CREATE TRIGGER trigger_ack_bi BEFORE INSERT ON
scm_main.tbl_ack
FOR EACH ROW
EXECUTE PROCEDURE trigger_ack_bi()
ALTER FUNCTION trigger_ack_bi() OWNER TO postgres;
I'd recommend setting column to be NOT NULL and creating a PK on it...
alter table scm_main.tbl_ack alter column ack_summary_id set NOT NULL;
alter table scm_main.tbl_ack add primary key (ack_summary_id);
it seems the trigger function is correct. But, it is running in silent mode. raising an exception was what I needed to make sure that duplication had been prevented. Thank you for your other solutions.
CREATE OR REPLACE FUNCTION trigger_ack_bi()
RETURNS trigger AS $$
--DECLARE
-- max_points INTEGER;
BEGIN
IF(TG_OP = 'INSERT') THEN
IF NEW.ack_summary_id IS NULL THEN
RAISE EXCEPTION 'summaryID cannot be null';
END IF;
IF NEW.ack_summary_id = (SELECT ack_summary_id FROM scm_main.tbl_ack WHERE scm_main.tbl_ack.ack_summary_id = NEW.ack_summary_id LIMIT 1) THEN
RAISE EXCEPTION 'duplication prevented..';
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END IF;
END;
$$LANGUAGE plpgsql;
CREATE TRIGGER trigger_ack_bi BEFORE INSERT ON
scm_main.tbl_ack
FOR EACH ROW
EXECUTE PROCEDURE trigger_ack_bi()