Как успешно ссылаться на другую таблицу перед вставкой с помощью триггера

#sql #plsql #triggers #oracle-apex

#sql #plsql #триггеры #oracle-apex

Вопрос:

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

Может ли кто-нибудь мне помочь?

 CREATE OR REPLACE TRIGGER t_MNRcontrole

BEFORE INSERT OR UPDATE 
ON registraties

DECLARE 
MNR_medewerkers number (SELECT MNR FROM MEDEWERKERS);

FOR EACH ROW
BEGIN 

IF :new.MNR <> MNR_medewerkers
THEN raise_application_error(-20111, 'Medewerker niet herkend!');

END IF;
END;
  

Полученное сообщение об ошибке
ORA-24344: success with compilation error

Ответ №1:

Оператор присваивания PL / SQL — это := или select x into y from z для заполнения из SQL-запроса.

FOR EACH ROW является частью спецификации триггера, а не кода PL / SQL.

Если :new.mnr отсутствует в родительской таблице, вы получите no_data_found исключение, а не несоответствующую переменную.

Рекомендуется, чтобы сообщения об ошибках включали подробную информацию о сбое.

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

Фиксированная версия будет выглядеть примерно так:

 create or replace trigger trg_mnrcontrole
    before insert or update on registraties
    for each row
declare
    mnr_medewerkers medewerkers.mnr%type;
begin
    select mw.mnr into mnr_medewerkers
    from   medewerkers mw
    where  mw.mnr = :new.mnr;

exception  
    when no_data_found then
        raise_application_error(-20111, 'Medewerker '||:new.mnr||' niet herkend!');
end;
  

Однако мы можем лучше реализовать этот вид проверки, используя ограничение внешнего ключа, например:

 alter table registraties add constraint registraties_mw_fk
foreign key (mnr) references medewerkers.mnr;
  

Комментарии:

1. Спасибо! Я добавил код ошибки, и я на самом деле не уверен, как сделать отступ, попробовал TAB , но, похоже, это не сработало. Только что нашел сайт, на котором говорится, что его можно изменить в настройках, поэтому я попробую это немного. Я думаю, что ваше решение должно работать, я не привык к этим SELECT INTO заявлениям. Я все еще знакомлюсь с возможностями. Большое спасибо за ваше объяснение.

2. Триггер — не лучший способ решить эту проблему — для этой цели существуют ограничения внешнего ключа. Вместо этого взгляните на это

3. Я не знаю, какой редактор вы используете, но я нахожу, что 4 пробела выполняют эту работу 🙂

Ответ №2:

Номер MNR_medewerkers (ВЫБЕРИТЕ MNR ИЗ MEDEWERKERS);

всегда будет сбой, потому что это не ЧИСЛО, если только в вашей таблице не будет только одной единственной записи, и даже тогда я не уверен, что PLSQL позволит ей пройти.

Более стандартным вариантом для этого было бы сначала объявить число, затем в codeblock вы выполняете SELECT INTO вместе с предложением WHERE, где вы убедитесь, что выбрали только одну конкретную строку из таблицы. Затем вы можете сравнить это число с новым.

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

 BEGIN
  SELECT 1
    INTO m_variable
    FROM table
   WHERE MNR = :new.MNR;
EXCEPTION
  WHEN TOO_MANY_ROWS THEN
    m_variable = 1;
  WHEN OTHERS THEN
    m_variable = 0;
END;
  

Заранее объявите переменную m_variable, а затем проверьте, соответствует ли она 0, а затем сообщите об ошибке.

Значение too_many_rows используется в случае, если в таблице с этим MNR имеется более одной строки, а ОСТАЛЬНЫЕ — для NO_DATA_FOUND, но я использую ДРУГИЕ для обработки всего остального, что может произойти, но, вероятно, не будет.

Кстати, это блок кода, который должен быть включен в основной блок кода, поэтому между вашими BEGIN и IF просто измените IF, чтобы проверить, равна ли переменная 0.

Комментарии:

1. Я чувствую, что ваш ответ должен сработать, однако я не могу заставить его работать. Чтобы уточнить, MNR — это PK в medewerkers , и я хочу проверить, известен ли сотрудник (MNR) при попытке регистрации (вставить строку в таблицу registraties ). Если нет, показать ошибку.