2013-07-14 3 views
0

У меня возникли проблемы с этим ниже кода, который является триггером используется в Oracle SQL:TRIGGER Oracle для предотвращения обновления или вставки

CREATE OR REPLACE TRIGGER TRG_TUTOR_BLOCK 
BEFORE INSERT OR UPDATE ON tutors 
FOR EACH ROW 
DECLARE 
BEGIN 
    IF :new.tutorName = :old.tutorName 
THEN 
    RAISE_APPLICATION_ERROR(-20101, 'A tutor with the same name currently exists.'); 
    ROLLBACK; 
END IF; 
END; 
/

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

После того, как я вставляю две записи с одинаковым tutorname, триггер не блокирует меня от его вставки. Кто-нибудь может сказать мне, в чем проблемы с этим кодированием? Ниже приведены формат выборки и значения вставки:

INSERT INTO tutors VALUES (tutorID, tutorName tutorPhone, tutorAddress, tutorRoom, loginID); 


INSERT INTO tutors VALUES ('13SAS01273', 'Tian Wei Hao', '019-8611123','No91, Jalan Wangsa Mega 2, 53100 KL', 'A302', 'TianWH'); 

ответ

1

Вам не нужен триггер для этого в Oracle.

Вы можете сделать это с помощью «уникального индекса» в столбце tutorName (см. http://docs.oracle.com/cd/B28359_01/server.111/b28310/indexes003.htm#i1106547).

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

+0

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

+0

Добавить триггер ДО ВСТАВКИ ИЛИ УДАЛЕНИЯ, который всегда выдает ошибку и выполняет откат. – Kamil

0

Проверьте случай в вашем теле триггера

IF :new.tutorName = :old.tutorName 

Он возвращает истину, если значение «tutorName» то же самое в новой и старой записи. Когда вы попытаетесь обновить какую-то ценность, вы получите

IF 'someTutorName' = 'someTutorName' 

, который вернет ИСТИННЫЙ. Вставка строки не может стрелять это правило, потому что вы пытаетесь сравнить что-то вроде этого:

'someTutorName' = NULL 

Этот случай всегда возвращает FALSE. Попробуйте использовать что-то вроде этого

CREATE OR REPLACE TRIGGER TRG_TUTOR_BLOCK 
BEFORE INSERT OR UPDATE ON tutors 
FOR EACH ROW 
DECLARE 
    rowsCount INTEGER; 
BEGIN 
    SELECT COUNT(*) FROM tutors WHERE tutorName is :new.tutorName INTO rowsCount; 
    IF rowsCount > 0 
THEN 
    RAISE_APPLICATION_ERROR(-20101, 'A tutor with the same name currently exists.'); 
    ROLLBACK; 
END IF; 
END; 
/

Но лучшим решением является один упомянутый Фриоль - использовать уникальный индекс путем выполнения SQL, как это

ALTER TABLE tutors 
ADD CONSTRAINT UNIQUE_TUTOR_NAME UNIQUE (tutorName); 
+0

Я не думаю, что это будет работать в триггере обновления, поскольку строка будет мутировать –

2

Trigger в примере Камиля выбросит ORA-04091, вы можете это увидеть собственными глазами here. ROLLBACK в триггере не требуется, он запускается неявно, когда триггер делает утверждение сбойным.

Вы можете запретить любой DML на столе с помощью altering it with read only clause:

alter table tutors read only; 

наконец, целостность должна быть declarated с integrity constraints и не с триггерами.

Удачи вам!

0

Если вы хотите полностью игнорировать запись строки в таблице вы можете следить за этим шаги

переименовать таблицу на что-то другое и создать представление с тем же именем и создать вместо триггера.

create table usermessages (id number(10) not null) 
GO 

alter table usermessages rename to xusermessages 
GO 

create or replace view usermessages as (select * from xusermessages) 
GO 

create or replace trigger usermessages_instead_of_trg 
    instead of insert or update on usermessages 
    for each row 
    begin 
    Null ; 
end ; 
GO 

insert into usermessages(123) 

Живой тест доступен здесь ниже

http://sqlfiddle.com/#!4/ad6bc/2

Смежные вопросы