Я хочу использовать оператор if внутри триггера, но значение if будет получено из другого оператора выбора.

Я сделал следующее:

create or replace 
Trigger MYTRIGGER
After Insert On Table1
Referencing Old As "OLD" New As "NEW" 
For Each Row 
Begin
  Declare Counter Int;
  Select Count(*) From Table2 Where Table2."Email" = :New.U_MAIL  Into Counter;
  IF Counter < 1 THEN
    //INSERT Statement here... 
  END IF;
End;

Моя логика проста: если такой же пользователь электронной почты существует, вставка не сработает.

Выше код не работал. Как мы можем это сделать?

1
isa 25 Дек 2014 в 16:00

2 ответа

Лучший ответ

Несколько синтаксических ошибок. Было бы ближе к такому:

create or replace 
Trigger MYTRIGGER
After Insert On Table1
Referencing Old As "OLD" New As "NEW" 
For Each Row 

DECLARE

  v_count NUMBER;

BEGIN

  SELECT COUNT(*)
    INTO v_count
    FROM Table2
    WHERE Email = :New.U_MAIL
  ;

  IF v_count > 0
  THEN
      RAISE_APPLICATION_ERROR(-20000, 'Not inserted...');
  END IF;

END;
2
Glenn 25 Дек 2014 в 14:19

Ваш подход неверен. Ссылочная целостность не должна осуществляться с помощью триггеров, она просто не может работать должным образом. См. Пример:

Connected to Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 
Connected as test@soft12c1

SQL> create table mail_1 (email varchar2(100));

Table created

SQL> create table mail_2 (email varchar2(100));

Table created

SQL> create trigger mail_1_check
  2    before insert on mail_1
  3    for each row
  4  declare
  5    cnt integer;
  6  begin
  7    select count(*) into cnt from mail_2 where email = :new.email;
  8    if cnt > 0 then
  9      raise_application_error(-20100, 'Email already exists');
 10    end if;
 11  end;
 12  /

Trigger created

SQL> insert into mail_2 values ('president@gov.us');

1 row inserted

SQL> insert into mail_1 values ('king@kingdom.en');

1 row inserted

SQL> insert into mail_1 values ('president@gov.us');

ORA-20100: Email already exists
ORA-06512: at "TEST.MAIL_1_CHECK", line 6
ORA-04088: error during execution of trigger 'TEST.MAIL_1_CHECK'

Похоже, что триггер работает правильно, но это неправда. Посмотрите, что произойдет, когда несколько пользователей будут работать одновременно.

-- First user in his session

SQL> insert into mail_2 values ('dictator@country.by');

1 row inserted

-- Second user in his session

SQL> insert into mail_1 values ('dictator@country.by');

1 row inserted

-- First user is his session

SQL> commit;

Commit complete

-- Second user is his session

SQL> commit;

Commit complete

-- Any user in any session 

SQL> select * from mail_1 natural join mail_2;

EMAIL
--------------------------------------------------------------------------------
dictator@country.by

Если для этой задачи используются триггеры, вам следует сериализовать любые попытки использовать эти данные, например, выполнить LOCK TABLE В ЭКСКЛЮЗИВНОМ РЕЖИМЕ, если не выполняется фиксация. Вообще это плохое решение. Для этой конкретной задачи вы можете использовать гораздо лучший подход:

Connected to Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 
Connected as test@soft12c1

SQL> create table mail_1_2nd(email varchar2(100));

Table created

SQL> create table mail_2_2nd(email varchar2(100));

Table created

SQL> create materialized view mail_check
  2    refresh complete on commit
  3  as
  4    select 1/0 data from mail_1_2nd natural join mail_2_2nd;

Materialized view created

ОК. Посмотрим, что, если мы попробуем использовать тот же адрес электронной почты:

-- First user in his session

SQL> insert into mail_1_2nd values ('dictator@gov.us');

1 row inserted

-- Second user in his session

SQL> insert into mail_2_2nd values ('dictator@gov.us');

1 row inserted

SQL> commit;

Commit complete

-- First user in his session

SQL> commit;

ORA-12008: error in materialized view refresh path
ORA-01476: divisor is equal to zero

SQL> select * from mail_1_2nd natural join mail_2_2nd;

EMAIL
--------------------------------------------------------------------------------

no rows selected 
1
Sanders the Softwarer 25 Дек 2014 в 16:28