Как проверить обновление значения столбца в триггере Oracle

Я использую 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;

Спасибо

«Я не хочу проверять: old.col1 <>: new.col1 для каждого столбца отдельно». Почему нет? в основном PL / SQL - это устаревший язык, не имеющий особых возможностей для рефлексии. Возможен обходной путь, но это зависит от того, чего именно вы пытаетесь избежать.
APC 18.03.2018 15:18

@apc Я отредактировал свой вопрос. Я хочу сделать это обычным образом и сделать это безопаснее. поместите столбцы, которые важны для запуска в таблице, и не помещайте много IF в мой триггер.

SaraB 19.03.2018 06:10

Да, я подозревал, что это именно то, что вы хотели.

APC 19.03.2018 09:15
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
3
1 177
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете определить глобальную функцию, подобную следующей:

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). Я не думаю, что это решает суть жалобы ОП, а именно то, что они не хотят проверять каждый столбец отдельно.

APC 18.03.2018 15:15
Ответ принят как подходящий

В комментарии вы сказали:

"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).

Другие вопросы по теме