Re: How to avoid UPDATE on same data in table ?

Поиск
Список
Период
Сортировка
От Condor
Тема Re: How to avoid UPDATE on same data in table ?
Дата
Msg-id 22cd5ff9ef7651d08628567eafad0de1@stz-bg.com
обсуждение исходный текст
Ответ на Re: How to avoid UPDATE on same data in table ?  (Adrian Klaver <adrian.klaver@aklaver.com>)
Ответы Re: How to avoid UPDATE on same data in table ?
Список pgsql-general
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



В списке pgsql-general по дате отправления:

Предыдущее
От: Pawan Sharma
Дата:
Сообщение: Restrict connection from pgadmin.
Следующее
От: Andrei Zhidenkov
Дата:
Сообщение: Re: How to avoid UPDATE on same data in table ?