Have you tried to use built-in suppress_redundant_updates_trigger[1] for this?
1. https://www.postgresql.org/docs/12/functions-trigger.html <https://www.postgresql.org/docs/12/functions-trigger.html> > On 3. Feb 2020, at 09:27, Condor <con...@stz-bg.com> wrote: > > On 02-02-2020 23:06, Adrian Klaver wrote: >> On 2/2/20 1:24 AM, Condor wrote: >>> Hello, >>> I'm using PostgreSQL 12.1 and trying to avoid update on table when data is >>> the same. I read somewhere if UPDATE is with the same data SQL server on >>> system level does not do update on table but don't know if that is true or >>> not. If that is not true I do: >>> First I create a function that should update data: >>> CREATE OR REPLACE FUNCTION log_last_chaged() RETURNS TRIGGER >>> LANGUAGE plpgsql >>> AS $$ >>> BEGIN >>> UPDATE status_table SET status0 = NEW.status0, lastchage = >>> CURRENT_TIMESTAMP WHERE rowid = OLD.rowid; >>> RETURN NEW; >>> END >>> $$; >>> then create table: >>> CREATE TABLE status_table ( >>> rowid INTEGER, >>> status0 INTEGER, >>> lastchage TIMESTAMP(0) WITHOUT TIME ZONE >>> ); >>> attach trigger: >> Why the DROP TRIGGER on card_sync_tbl? >> More below. >>> DROP TRIGGER last_changes ON card_sync_tbl; >>> CREATE TRIGGER last_changes >>> BEFORE UPDATE ON status_table >>> FOR EACH ROW >>> WHEN (OLD.* IS DISTINCT FROM NEW.*) >>> EXECUTE FUNCTION log_last_chaged(); >>> insert first data: >>> INSERT INTO status_table (rowid, status0) VALUES (11, 1); >>> INSERT INTO status_table (rowid, status0) VALUES (12, 2); >>> and check do everything work fine: >>> UPDATE status_table SET status0 = 1 WHERE rowid = 11; >>> UPDATE status_table SET status0 = 4 WHERE rowid = 12; >>> I receive something on rowid 12 that probably is error: >>> SQL statement "UPDATE status_table SET status0 = NEW.status0, lastchage = >>> CURRENT_TIMESTAMP WHERE rowid = OLD.rowid" >>> PL/pgSQL function log_last_chaged() line 3 at SQL statement >>> After quick look on duckduckgo I change the function to this: >>> CREATE OR REPLACE FUNCTION log_last_chaged() RETURNS TRIGGER >>> LANGUAGE plpgsql >>> AS $$ >>> BEGIN >>> NEW.lastchage := CURRENT_TIMESTAMP; >>> RETURN NEW; >>> END >>> $$; >>> and everything seems work now, but that break the idea update not to hit >>> table if data is the same. >> Some changes based on: >> https://www.postgresql.org/docs/12/sql-createtrigger.html >> "In a BEFORE trigger, the WHEN condition is evaluated just before the >> function is or would be executed, so using WHEN is not materially >> different from testing the same condition at the beginning of the >> trigger function. Note in particular that the NEW row seen by the >> condition is the current value, as possibly modified by earlier >> triggers. " >> https://www.postgresql.org/docs/12/plpgsql-trigger.html#PLPGSQL-DML-TRIGGER >> "Row-level triggers fired BEFORE can return null to signal the trigger >> manager to skip the rest of the operation for this row (i.e., >> subsequent triggers are not fired, and the INSERT/UPDATE/DELETE does >> not occur for this row)." >> CREATE OR REPLACE FUNCTION public.log_last_chaged() >> RETURNS trigger >> LANGUAGE plpgsql >> AS $function$ >> BEGIN >> IF OLD.* IS DISTINCT FROM NEW.* THEN >> RAISE NOTICE 'UPDATE'; >> NEW.lastchage := CURRENT_TIMESTAMP; >> RETURN NEW; >> ELSE >> RETURN NULL; >> END IF; >> END >> $function$ >> CREATE TRIGGER last_changes >> BEFORE UPDATE ON status_table >> FOR EACH ROW >> EXECUTE FUNCTION log_last_chaged(); >> test=> INSERT INTO status_table (rowid, status0) VALUES (11, 1); >> INSERT 0 1 >> test=> INSERT INTO status_table (rowid, status0) VALUES (12, 2); >> INSERT 0 1 >> test=> select ctid, * from status_table ; >> ctid | rowid | status0 | lastchage >> -------+-------+---------+----------- >> (0,1) | 11 | 1 | >> (0,2) | 12 | 2 | >> (2 rows) >> test=> UPDATE status_table SET status0 = 1 WHERE rowid = 11; >> UPDATE 0 >> test=> select ctid, * from status_table ; >> ctid | rowid | status0 | lastchage >> -------+-------+---------+----------- >> (0,1) | 11 | 1 | >> (0,2) | 12 | 2 | >> (2 rows) >> NOTE: UPDATE 0 and no change in ctid >> test=> UPDATE status_table SET status0 = 4 WHERE rowid = 12; >> NOTICE: UPDATE >> UPDATE 1 >> test=> select ctid, * from status_table ; >> ctid | rowid | status0 | lastchage >> -------+-------+---------+--------------------- >> (0,1) | 11 | 1 | >> (0,3) | 12 | 4 | 02/02/2020 13:03:21 >> (2 rows) >> NOTE: UPDATE 1 and ctid change. >>> Any body can help with some hint ? Also I want to know why my first >>> function does not work, probably loop is happened if trigger does not stop >>> update to be sent to table on rowid 12 or syntax error. >>> Regards, >>> HS > > Thank you for detailed explanation. > Have a good day. > > Regards, > HS > >