PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

W ramach funkcji wyzwalacza, jak uzyskać, które pola są aktualizowane?

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ver.2 BŁĄD PyGreSQL:from _pg import * ImportError:Ładowanie DLL nie powiodło się:Nie można znaleźć określonego modułu

  2. Pandy zapisują ramkę danych do innego schematu postgresql

  3. Jak wykonać tę samą agregację w każdej kolumnie, nie wymieniając kolumn?

  4. Jak sprawić, by PyPy, Django i PostgreSQL współpracowały ze sobą?

  5. Radzenie sobie z powolnymi zapytaniami w PostgreSQL