PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

В рамките на функция за задействане, как да получите кои полета се актуализират

Ако „източник“ не „изпрати идентификатор“, колоната ще остане непроменена. Тогава не можете да откриете дали текущата UPDATE е направено от същия източник като последния или от източник, който изобщо не е променил колоната. С други думи:това не работи правилно.

Ако "източникът" може да бъде идентифициран чрез която и да е функция за информация за сесията, можете да работите с нея. Като:

NEW.column = session_user;

Безусловно за всяка актуализация.

Общо решение

Намерих начин как да реша първоначалния проблем. Колоната ще бъде зададена на стойност по подразбиране в всяко актуализирайте, където колоната не е актуализирана (не е в SET списък на UPDATE ).

Ключов елемент е задействане на колона въведен в PostgreSQL 9.0 - специфичен за колона тригер, използващ UPDATE OF column_name клауза.

Задействането ще се задейства само ако поне една от изброените колони е спомената като цел на UPDATE команда.

Това е единственият прост начин, който открих, за да разгранича дали колона е актуализирана с нова стойност, идентична на старата, от която изобщо не е актуализирана.

Един може също така анализирайте текста, върнат от current_query() . Но това изглежда сложно и ненадеждно.

Функции за задействане

Предполагам, че има колона col дефиниран NOT NULL .

Стъпка 1: Задайте col до NULL ако е непроменено:

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
  RETURNS trigger AS
$func$
BEGIN
   IF OLD.col = NEW.col THEN
      NEW.col := NULL;      -- "impossible" value
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Стъпка 2: Връщане към старата стойност. Тригерът се задейства само ако стойността действително е актуализирана (вижте по-долу):

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
  RETURNS trigger AS
$func$
BEGIN
   IF NEW.col IS NULL THEN
      NEW.col := OLD.col;
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Стъпка 3: Сега можем да идентифицираме липсващата актуализация и вместо това да зададем стойност по подразбиране:

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
  RETURNS trigger AS
$func$
BEGIN
   IF NEW.col IS NULL THEN
      NEW.col := 'default value';
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Задействания

Задействане за Стъпка 2 се изстрелва на колона!

CREATE TRIGGER upbef_step1
  BEFORE UPDATE ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step1();

CREATE TRIGGER upbef_step2
  BEFORE UPDATE OF col ON tbl                -- key element!
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step2();

CREATE TRIGGER upbef_step3
  BEFORE UPDATE ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step3();

Имена на задействания са подходящи, тъй като се задействат по азбучен ред (всички са BEFORE UPDATE )!

Процедурата може да бъде опростена с нещо като "задействания за не-колона" или друг начин за проверка на целевия списък на UPDATE в спусък. Но не виждам решение за това.

Ако col може да бъде NULL , използвайте всяка друга "невъзможна" междинна стойност и проверете за NULL допълнително в тригерна функция 1:

IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
    NEW.col := '#impossible_value#';
END IF;

Адаптирайте съответно останалото.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да конвертирам интервал в брой часове с postgres?

  2. Колко записа мога да съхранявам в 5 MB PostgreSQL на Heroku?

  3. Уникално ограничение за комбинация от две колони?

  4. Как да инсталирате PgBackRest

  5. Използвайте двоична таблица COPY FROM с psycopg2