Я использую UPDATING (col_name), чтобы проверить, обновлено ли значение столбца внутри триггера. Но большая проблема в том, что эта команда не проверяет значения: old и: new объектов. UPDATING (col_name) истинно, если col_name существует в набор части запроса даже со старым значением.
Не хочу проверять: old.col1 <>: new.col1 для каждого столбца отдельно.
Как я могу правильно проверить изменение значения столбца?
Я хочу сделать это в общем виде. нравиться :
SELECT col_name bulk collect INTO included_columns FROM trigger_columns where tbl_name ='name';
l_idx := included_columns.first;
while (l_idx is not null)
loop
IF UPDATING(included_columns(l_idx)) THEN
//DO STH
return;
END IF;
l_idx := included_columns.next(l_idx);
end loop;
Спасибо
@apc Я отредактировал свой вопрос. Я хочу сделать это обычным образом и сделать это безопаснее. поместите столбцы, которые важны для запуска в таблице, и не помещайте много IF в мой триггер.
Да, я подозревал, что это именно то, что вы хотели.


Вы можете определить глобальную функцию, подобную следующей:
CREATE OR REPLACE FUNCTION NUMBER_HAS_CHANGED(pinVal_1 IN NUMBER,
pinVal_2 IN NUMBER)
RETURN CHAR
IS
BEGIN
IF (pinVal_1 IS NULL AND pinVal_2 IS NOT NULL) OR
(pinVal_1 IS NOT NULL AND pinVal_2 IS NULL) OR
pinVal_1 <> pinVal_2
THEN
RETURN 'Y';
ELSE
RETURN 'N';
END IF;
END NUMBER_HAS_CHANGED;
Теперь в вашем триггере вы просто пишете
IF NUMBER_HAS_CHANGED(:OLD.COL1, :NEW.COL1) = 'Y' THEN
-- whatever
END IF;
Обратите внимание, что эта функция определена для возврата CHAR, поэтому при необходимости ее также можно вызывать из операторов SQL - например, в выражении CASE. Помните, что в Oracle в базе данных нет типа BOOLEAN - только в PL / SQL.
Вы, вероятно, захотите создать дополнительные версии этой функции для обработки значений VARCHAR2 и DATE, для начала, но поскольку это вопрос замены типов данных и изменения имени функции, я позволю вам получить удовольствие от написания их. :-)
Удачи.
Все это заменяет серию явных операторов if :old.colname != :new.colname серией обращений к number_has_changed(:old.colname, :new.colname). Я не думаю, что это решает суть жалобы ОП, а именно то, что они не хотят проверять каждый столбец отдельно.
В комментарии вы сказали:
"I want to do this in a generic way and manage it safer. put columns which are important to trigger in a table and don't put many IF in my trigger. "
Я подозревал, что это то, что вы хотели. Единственный способ добиться этого - использовать динамический SQL для сборки и выполнения блока PL / SQL. Это сложное решение без материальной выгоды.
Боюсь, я посмеялся над тем, как вы там использовали "безопаснее". Триггеры и без того ужасны: они затрудняют понимание того, что происходит в базе данных, и могут привести к непредвиденным проблемам с масштабируемостью. Не усугубляйте их, добавляя в смесь динамический SQL. Динамический SQL сложен, потому что он превращает ошибки компиляции в ошибки времени выполнения.
Что вы возражаете против жесткого кодирования имен столбцов и операторов IF в триггере? Это безопаснее, потому что триггер скомпилирован. Проверить логику триггера проще, потому что код - прямо там.
Если это просто нежелание печатать, вы можете сгенерировать источник триггера из представлений словаря данных (например, all_tab_cols) или даже ваших собственных таблиц метаданных, если необходимо (например, trigger_columns).