возрастной контроль 2 для пл / кв.

Я пытаюсь выяснить, в каком возрасте сотрудник начал работать. если ему исполнилось 16 лет, он должен сообщить об ошибке «Ошибка при вводе даты рождения». так что мой триггер создан, но мой триггер не работает, я получаю эту ошибку: ORA-01422: Точный поиск возвращает больше, чем запрошенное количество строк

я не могу найти проблему вот код:

SET SERVEROUTPUT ON
ACCEPT Birthday PROMPT ' Pleas give you Date of birth: ' 
CREATE OR REPLACE TRIGGER T_Controll
before INSERT ON  meine_Firma -- Table
FOR EACH ROW
DECLARE
V_Berufstart            meine_Firma.Hiredate%TYPE; --Job begin
V_Geburtsdatum          DATE; -- Date of birth
V_Alter                 number:=0; -- AGE
SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;
BEGIN
V_Geburtsdatum:=('&Birthday');  
V_Alter:= Round(MONTHS_BETWEEN(V_Berufstart,V_Geburtsdatum)-2)/12;
IF 16 > V_Alter THEN   
RAISE_APPLICATION_ERROR(-20201,'Error when entering the date of birth');
END IF;
END;
/

ВЫКЛЮЧИТЬ СЕРВЕРУ ВЫХОД

Если ему меньше 16 лет, он может не работать извините, мой английский не очень хорош (=

Всего 2 ответа


В этом скрипте есть гораздо более серьезная проблема, чем ошибка, которую вы получаете. Даже после исправления, предложенного @ShaunPeterson, он все равно потерпит неудачу, он НЕ БУДЕТ выдавать ошибку, он просто не будет работать так, как вы ожидаете. Проблема в том, что вы не смогли понять переменные замещения - использование & name (в частности, здесь & Birthday.) Я буду использовать & Birthday в следующем, но обсуждение относится к ЛЮБЫМ / ВСЕМ переменным замещения.

люди не понимают, почему они не могут использовать переменные подстановки "&" в своих процедурах и функциях PL / SQL для запроса ввода во время выполнения. Надеемся, что эта статья поможет вам понять, в чем заключаются различия, чтобы вы могли понять, где и когда их использовать.

  1. Переменные подстановки Подсказка в названии ... "подстановка". Это относится к значениям, подставляемым в код перед его отправкой в ​​базу данных. Эти замены выполняются используемым интерфейсом

Эффект этой замены заключается в том, что строка, содержащая переменную подстановки, физически переписывается интерфейсом, заменяющим% Birthday. В этом случае, если вы не введете значение или дату 2000-05-19, оператор до и после замены будет

  • ДО: V_Geburtsdatum: = ('& День рождения');
  • ПОСЛЕ: V_Geburtsdatum: = (''); ИЛИ V_Geburtsdatum: = ('2000-05-19');

В любом случае, компилятор видит после. он вообще не видит% Birthday. Более того, при запуске триггер не будет запрашивать значение. Что касается компилятора, это жестко закодированное значение, которое никогда не изменится. Помимо этого, триггер или любой другой сценарий PLSQL (хранимый или анонимный) никогда не запрашивает значения , они фактически не способны сделать это, поскольку они не являются частью языка. Любая подсказка через программное обеспечение вашего интерфейса не plsql.

Я собираюсь предложить способ вообще избежать триггера. Начало работы с мылом: триггеры ПЛОХО, они полезны для назначения ключей автоинкремента (до 12с), ведения журнала, очень ограниченного аудита и т. Д. Однако для бизнес-правил они должны быть последним средством. Хорошо, сойди с мыла.

Первым делом нужно сделать столбцы meine_Firma.Hiredate и meine_Firma.Geburtsdatum НЕ пустыми (если их еще нет). Если любой из них равен NULL, вы не можете ничего с ним вычислить, результатом будет NULL. Во-вторых, создайте новый столбец age_at_hire (или любой другой) в качестве виртуального столбца, затем установите для него ограничение проверки. И вуаля триггер больше не нужен. Смотрите скрипку для демонстрации.
Итак, предлагаемое изменение (ДА, вам, вероятно, придется сначала очистить неверные данные):

alter table meine_Firma modify 
          ( hiredate     not null
          , Geburtsdatum not null
          ) ;
alter table meine_Firma add                           
          ( age_at_hire integer generated always as (trunc(months_between(hiredate,Geburtsdatum))) virtual
          , constraint check_age_at_hire check (age_at_hire >= 16*12)
          );

В любом случае, я надеюсь, что вы получите представление о переменных подстановки на будущее. И учитесь избегать триггеров. Удачи.


Причина, по которой вы получаете эту конкретную ошибку, заключается в том, что нижеприведенный select выберет ВСЕ строки из meine_Firma, так как нет выражения where

SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;

Однако, поскольку вы находитесь в триггере, вам не нужно ничего выбирать, используя переменную: NEW bind. Так что вы можете просто использовать

V_Berufstart := :NEW.HIREDATE;

Если бы это был триггер обновления, то была бы объявлена ​​переменная связывания: NEW и: OLD, чтобы вы могли получить доступ к значениям OLD и NEW. Поскольку это триггер вставки, то: OLD будет просто нулевым, поскольку старых значений нет.