Неверная ошибка переменной привязки с оператором select внутри триггера в Oracle

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

Мне также нужно вставить, была ли операция вставкой, обновлением или удалением

CREATE OR REPLACE TRIGGER triggername
AFTER INSERT OR UPDATE OR DELETE
ON tablename

DECLARE
operation_type VARCHAR2;
changed_id VARCHAR2;
BEGIN

IF UPDATING
THEN operation_type := 'Update';

ELSE IF INSERTING
THEN operation_type := 'Insert';

ELSE IF DELETING
THEN operation_type := 'Delete';

END IF;


SELECT id
FROM tablename
WHERE :OLD.record1 != :NEW.record1
OR :OLD.record2 != :NEW.record2
OR :OLD.record3 != :NEW.record3
OR :OLD.record4 != :NEW.record4
OR :OLD.record5 != :NEW.record5
OR :OLD.record6 != :NEW.record6;

INTO changed_id;

  INSERT INTO trigger_table.id VALUES(changed_id);
  INSERT INTO trigger_table.type VALUES(operation_type);
END;
/

я получаю сообщение об ошибке

«ПЛОХОЕ ИМЯ ПРИВЯЗКИ: НОВОЕ» или «ПЛОХОЕ ИМЯ ПРИВЯЗКИ: СТАРОЕ» для каждого из: НОВОЕ или : СТАРОЕ

показано выше


person Steve Robinson    schedule 13.05.2015    source источник
comment
Вы можете ссылаться на значения :OLD и :NEW только в TRIGGER ROW LEVEL TRIGGER. Вы должны использовать FOR EACH ROW.   -  person Lalit Kumar B    schedule 13.05.2015
comment
Триггеры не поддерживают синтаксис для проверки всей записи. Вам необходимо протестировать столбец за столбцом.   -  person APC    schedule 13.05.2015
comment
Посмотрите ответ на похожий вопрос SO о триггерах аудита.   -  person APC    schedule 13.05.2015


Ответы (2)


Есть несколько проблем с вашим кодом триггера:

  1. тип_операции VARCHAR2;

Вы должны объявить размер переменной. иначе вы получите ошибку

PLS-00215: ограничения длины строки должны находиться в диапазоне (1 .. 32767)

Например, измените его как:

operation_type VARCHAR2(20);
changed_id VARCHAR2(20);
  1. Описание SELECT .. INTO
SELECT id
FROM tablename
WHERE :OLD.record1 != :NEW.record1
OR :OLD.record2 != :NEW.record2
OR :OLD.record3 != :NEW.record3
OR :OLD.record4 != :NEW.record4
OR :OLD.record5 != :NEW.record5
OR :OLD.record6 != :NEW.record6;

INTO changed_id;

Это синтаксически неверно. Предложение INTO должно находиться между предложениями SELECT и FROM:

SELECT id 
  INTO changed_id 
FROM tablename 
 WHERE ...
  1. ГДЕ :OLD.record1 != :NEW.record1

Это ваш первоначальный вопрос относительно ошибки неправильной привязки переменной.

Чтобы ссылаться на значения :OLD и :NEW, необходимо создать триггер ROW LEVEL, который должен включать следующее условие:

FOR EACH ROW
  1. ВСТАВЬТЕ операторы
INSERT INTO trigger_table.id VALUES(changed_id);
INSERT INTO trigger_table.type VALUES(operation_type);

Вы должны вставить одну строку, а не две строки с двумя операторами вставки. Кроме того, trigger_table.id является неправильным синтаксисом. Вы должны упомянуть имена столбцов в круглых скобках.

Например,

INSERT INTO trigger_table(column1, column2) VALUES
          (changed_id, operation_type);
person Lalit Kumar B    schedule 13.05.2015

Когда вы пытаетесь использовать :NEW для удаления и :OLD для создания в триггере, вы увидите эти ошибки.

Было бы лучше переместить операторы выбора и вставки внутрь

IF INSERTING THEN ... END IF;
IF UPDATING THEN ... END IF;
IF DELETING THEN ... END IF;

использовать переменные :NEW и :OLD

person S.Krishna    schedule 13.05.2015
comment
Я не уверен, что следую. Операторы :NEW и :OLD предназначены для определения того, какая запись в таблице была изменена. Есть ли более простой способ выяснить, какая запись была изменена? - person Steve Robinson; 13.05.2015
comment
Ты прав. Но поскольку ваш триггер обрабатывает все транзакции создания, обновления и удаления одинаково и пытается запустить операторы выбора и вставки, вы видите ошибку. вместо того, чтобы выбирать и вставлять вне конструкций «при создании» и «при удалении», переместите их внутрь. Когда запись создается, в :OLD нет значения, а когда запись удаляется, в :NEW нет значения. - person S.Krishna; 13.05.2015
comment
Нет, это не причина ошибки плохой привязки переменной. Причина в том, что для ссылки на значения :OLD и :NEW должен быть триггер ROW LEVEL, которому требуется условие FOR EACH ROW. - person Lalit Kumar B; 13.05.2015