Ответ 1
Как @A.H. написал в своем комментарии, если "источник" не "отправляет идентификатор", столбец не изменится. Тогда вы не можете определить, был ли текущий UPDATE выполнен тем же источником, что и последний, или источником, который вообще не менял столбца. Другими словами: это не работает должным образом.
Если "источник" идентифицируется любым из этими функциями информации сеанса, вы можете с этим справиться. Как:
NEW.column = session_user;
Безоговорочно для каждого обновления.
Общее решение
Я нашел способ решения исходной проблемы. Столбец будет установлен в значение по умолчанию в любом, где столбец не обновлен (не в SET
списке UPDATE
).
Ключевым элементом является триггеры для столбцов, представленные в PostgreSQL 9.0:
Триггер срабатывает только в том случае, если хотя бы один из перечисленных столбцов упомянутый в качестве цели команды UPDATE.
Это единственный простой способ, который я нашел, чтобы отличить, был ли обновлен столбец с новым значением, идентичным старому значению или вообще не обновленным.
Можно проанализировать текст, возвращенный current_query()
.
Я предполагаю, что столбец col
определен NOT NULL
.
- Шаг 1: установите
col
наNULL
, если он не изменился:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
RETURNS trigger AS
$BODY$
BEGIN
IF OLD.col = NEW.col THEN
NEW.col := NULL; -- "impossible" value
END IF;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
- Шаг 2: возврат к старому значению. Триггер будет запущен, только если значение было фактически обновлено:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
RETURNS trigger AS
$BODY$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := OLD.col;
END IF;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
- Шаг 3. Теперь мы можем определить недостающее обновление и установить значение по умолчанию:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
RETURNS trigger AS
$BODY$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := 'default value';
END IF;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
Реализовать триггеры, step2 - триггер за столбец:
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();
Имена триггеров актуальны, потому что они будут запущены в алфавитном порядке!
Процедура может быть упрощена, если у нас есть что-то вроде "триггеров без столбца" или любой другой способ легко проверить целевой список UPDATE
в триггере.
Если ваша колонка может быть NULL
, используйте любой другой "невозможный" темп. значение и проверьте для NULL
дополнительно:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;