Триггер базы данных SQL ORA-00904 - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь ввести имя клиента, дату начала и название корабля в таблицу аудита, если номер оценки бронирования равен 2. Я получаю ошибку неверного идентификатора, когда имя, которое я использую, находится в таблице бронирования. Сейчас я просто пытаюсь получить имя клиента в таблице аудита, поэтому в других столбцах получено значение null.

Это код, который у меня есть, я не вижу, где я ошибаюсь:

CREATE OR REPLACE TRIGGER EVALUATION
BEFORE INSERT OR UPDATE OR DELETE ON BOOKING
FOR EACH ROW 
WHEN (NEW.BOOKING_EVALUATION = 2)
DECLARE

custname  VARCHAR(20);
sdate    DATE;
shname   VARCHAR(50);

BEGIN

SELECT CUSTOMER_NAME INTO custname FROM customer WHERE CUSTOMER_NAME = NEW.CUSTOMER_NAME;


IF INSERTING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:NEW.VOYAGES_ID,custname,NULL,NULL,:NEW.BOOKING_EVALUATION);
END IF;


IF UPDATING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
END IF;


IF DELETING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
END IF;
END;
/

Это ошибка, которую я получаю:

9/1 PL / SQL: оператор SQL игнорируется
9/67 PL / SQL: ORA-00904: «НОВЫЙ». «CUSTOMER_NAME»: неверный идентификатор

1 Ответ

0 голосов
/ 02 июля 2018

Вам необходимо использовать поле из псевдозаписи NEW, и, поскольку таблица, к которой относится триггер, имеет только идентификатор, его необходимо использовать для поиска:

SELECT CUSTOMER_NAME
INTO custname
FROM customer
WHERE CUSTOMER_ID = :NEW.CUSTOMER_ID;

Обратите внимание на префикс : для NEW, а также на изменение имени столбца / поля.

Это не совсем работает для ветви IF DELETING, так как псевдокорд NEW в этом случае будет пустым - заполняется только OLD. Таким образом, вам нужна дополнительная логика, чтобы получить имя клиента на основе OLD или NEW в зависимости от инициирующего события, и на основе того, что вы используете OLD в ветви UPDATING, вам может понадобиться и старый идентификатор клиента там.

Проверка WHEN (NEW.BOOKING_EVALUATION = 2) не будет работать и при удалении, по той же причине.

Так что вы можете сделать:

CREATE OR REPLACE TRIGGER EVALUATION
BEFORE INSERT OR UPDATE OR DELETE ON BOOKING
FOR EACH ROW 
DECLARE

  custname  VARCHAR(20);

BEGIN

  IF INSERTING AND :NEW.BOOKING_EVALUATION = 2 THEN
    SELECT CUSTOMER_NAME
    INTO custname
    FROM customer
    WHERE CUSTOMER_ID = :NEW.CUSTOMER_ID;

    INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
    VALUES(:NEW.VOYAGES_ID,custname,NULL,NULL,:NEW.BOOKING_EVALUATION);
  END IF;

  IF (UPDATING OR DELETING) AND :OLD.BOOKING_EVALUATION = 2 THEN
    SELECT CUSTOMER_NAME
    INTO custname
    FROM customer
    WHERE CUSTOMER_ID = :OLD.CUSTOMER_ID;

    INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
    VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
  END IF;
END;
/

в зависимости от того, хотите ли вы записать обновление, если старое, новое или BOOKING_EVALUATION равно 2. Эта версия смотрит только на OLD в UPDATING OR DELETING, поскольку это другие значения, которые вы используете для вставьте, но можете легко проверить либо, либо вы можете снова разделить UPDATING и DELETING. Или вы можете изменить первую проверку на:

...
BEGIN

  IF (INSERTING OR UPDATING) AND :NEW.BOOKING_EVALUATION = 2 THEN
...

Это зависит от того, какие сценарии вы хотите записать и какие значения вы хотите записать для них.


Если вы получили ошибку компиляции, либо запустите show errors, либо запросите представление user_errors, чтобы увидеть фактические ошибки. Если вы получите ORA-04098, то триггер, на который ссылается ошибка, недействителен - это было либо во время компиляции, либо (реже здесь я думаю) структура таблицы изменилась с момента последней успешной компиляции.

Возможно, вы создали несколько триггеров. Посмотрите на вывод

select trigger_name, status from user_triggers where table_name = 'BOOKING';

чтобы увидеть, сколько триггеров существует против этой таблицы (хотя это может быть в другом месте) и как они называются - если их больше одного, то посмотрите, есть ли у вас более ранняя попытка с другим именем, которое вам нужно отбросить.

И посмотрите на

select object_name, status from user_objects where object_type = 'TRIGGER';

, чтобы увидеть все триггеры, которые вы определили, и найти любые недействительные. Затем вы можете вернуться к представлению user_triggers, чтобы увидеть, против каких таблиц они действуют, если это не очевидно из их имен.

Что бы ни было недействительным, причина будет видна в user_errors.

...