Как создать триггер в Oracle, который будет ограничивать вставку и обновлять запросы к таблице на основе условия - PullRequest
2 голосов
/ 11 марта 2012

У меня есть таблица счетов, как эта -

create table account
(
acct_id int,
cust_id int,
cust_name varchar(20)  
)

insert into account values(1,20,'Mark');
insert into account values(2,23,'Tom');
insert into account values(3,24,'Jim');

Я хочу создать триггер, который будет гарантировать, что никакие записи не могут быть вставлены или обновлены в таблице счетов с acct_id как 2 и cust_id как 23.

Мой код -

create trigger tri_account
before insert or update
on account
for each row
begin
    IF (:new.acct_id == 2 and :new.cust_id == 23) THEN 
        DBMS_OUTPUT.PUT_LINE('No insertion with id 2 and 23.');
rollback;
    END IF; 
end;

поэтому этот триггер создан, но с ошибкой компиляции. теперь, когда я вставляю любую запись с acct_id как 2 и cust_id как 23, это разрешает. Но я получаю сообщение об ошибке ORA-04098: триггер 'OPS $ 0924769.TRI_ACCOUNT' недействителен и не прошел повторную проверку

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

Ответы [ 4 ]

19 голосов
/ 11 марта 2012
  1. Оператор равенства в Oracle равен =, а не ==.
  2. Вы не можете зафиксировать или откатить в триггере.Вы можете вызвать исключение, которое приводит к сбою оператора триггера и его откату (хотя существующая транзакция не обязательно будет откатана).
  3. Не похоже, что этот триггер был успешно скомпилирован при его создании.Если вы используете SQL * Plus, вы можете набрать show errors после создания объекта PL / SQL, чтобы увидеть ошибки компиляции.
  4. Никогда не пишите код, который зависит от того, может ли вызывающая сторона видеть вывод изDBMS_OUTPUT.Большинство приложений этого не делают, поэтому большинство приложений не будут знать, что операция DML не удалась, если ваш триггер просто попытается записать в буфер DBMS_OUTPUT.

Соединяя эти элементы вместе, вы можете написать что-то вроде

create trigger tri_account
before insert or update
on account
for each row
begin
    IF (:new.acct_id = 2 and :new.cust_id = 23) THEN 
        raise_application_error( -20001, 'No insertion with id 2 and 23.');
    END IF; 
end;
3 голосов
/ 11 марта 2012

Триггер более гибкий, но вы также можете сделать это с помощью ПРОВЕРКИ:

ALTER TABLE account ADD CONSTRAINT check_account CHECK ( acct_id != 2 OR cust_id != 23 )
ENABLE NONVALIDATE;

Предложение NONVALIDATE гарантирует, что проверочное ограничение не будет пытаться проверять существующие данные, хотя оно будет проверять все будущие данные.

Надеюсь, это поможет.

1 голос
/ 31 января 2013
IF (:new.acct_id = 2 and :new.cust_id = 23) THEN 

должно быть OR, а не and.

0 голосов
/ 09 августа 2014

При использовании условных проверок вам не нужно использовать двоеточия (:). Это всегда приведет к ошибкам.

Примечание: исключать двоеточие только в тех случаях, когда выполняется проверка условий.

...