Jeśli „źródło” nie „wysyła identyfikatora”, kolumna pozostanie niezmieniona. Wtedy nie możesz wykryć, czy bieżąca UPDATE
zostało wykonane przez to samo źródło co ostatnie lub przez źródło, które w ogóle nie zmieniło kolumny. Innymi słowy:to nie działa poprawnie.
Jeśli „źródło” można zidentyfikować za pomocą dowolnej funkcji informacji o sesji, możesz z tym pracować. Na przykład:
NEW.column = session_user;
Bezwarunkowo dla każdej aktualizacji.
Ogólne rozwiązanie
Znalazłem sposób na rozwiązanie pierwotnego problemu. Kolumna zostanie ustawiona na wartość domyślną w dowolny zaktualizuj, gdy kolumna nie jest aktualizowana (nie w SET
lista UPDATE
).
Kluczowym elementem jest wyzwalacz na kolumnę wprowadzony w PostgreSQL 9.0 - wyzwalacz specyficzny dla kolumny przy użyciu UPDATE OF
column_name
klauzula.
Reguła zostanie uruchomiona tylko wtedy, gdy co najmniej jedna z wymienionych kolumn zostanie wymieniona jako cel UPDATE
polecenie.
To jedyny prosty sposób, jaki znalazłem, aby odróżnić, czy kolumna została zaktualizowana o nową wartość identyczną ze starą, czy w ogóle nie zaktualizowaną.
Jeden może przeanalizuj także tekst zwrócony przez current_query()
. Ale to wydaje się trudne i niewiarygodne.
Funkcje wyzwalania
Zakładam kolumnę col
zdefiniowany NOT NULL
.
Krok 1: Ustaw col
na NULL
jeśli bez zmian:
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;
Krok 2: Przywróć starą wartość. Wyzwalacz zostanie uruchomiony tylko wtedy, gdy wartość została faktycznie zaktualizowana (patrz poniżej):
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;
Krok 3: Teraz możemy zidentyfikować brakującą aktualizację i zamiast tego ustawić wartość domyślną:
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;
Wyzwalacze
Wyzwalacz kroku 2 jest wystrzeliwany na kolumnę!
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();
Nazwy wyzwalaczy są istotne, ponieważ są uruchamiane w kolejności alfabetycznej (wszystkie są BEFORE UPDATE
)!
Procedurę można uprościć za pomocą czegoś takiego jak "wyzwalacze nie-kolumnowe" lub jakikolwiek inny sposób sprawdzenia listy docelowej UPDATE
w spuście. Ale nie widzę na to żadnego uchwytu.
Jeśli col
może być NULL
, użyj innej „niemożliwej” wartości pośredniej i sprawdź, czy nie ma wartości NULL
dodatkowo w funkcji wyzwalacza 1:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
Dostosuj resztę odpowiednio.