Ако „източник“ не „изпрати идентификатор“, колоната ще остане непроменена. Тогава не можете да откриете дали текущата 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;
Адаптирайте съответно останалото.