TRIGGER Oracle防止更新或插入

时间:2013-07-14 16:21:20

标签: oracle

我遇到以下代码问题,这是Oracle SQL中使用的触发器:

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');

4 个答案:

答案 0 :(得分:2)

卡米尔示例中的触发器将抛出ORA-04091,您可以亲眼看到here。触发器中的ROLLBACK是不必要的,当触发器使语句失败时,它会隐式运行。

您可以altering it with read only clause禁止表格中的任何DML:

alter table tutors read only;

最后,完整性应使用integrity constraints声明,而不是使用触发器声明。

祝你好运!

答案 1 :(得分:1)

在Oracle中,您不需要触发此操作。

您可以在tutorName列上使用“唯一索引”执行此操作(请参阅http://docs.oracle.com/cd/B28359_01/server.111/b28310/indexes003.htm#i1106547)。

注意:关于你的触发器,它无法检查具有相同tutorName的另一条记录,因为它没有扫描具有相同tutorName的另一条记录的教师表,它只是比较你正在创建的行的tutorName值(在此case,old.tutorName只是NULL,因为该行还不存在。)

答案 2 :(得分:0)

检查您的触发器主体中的案例

IF :new.tutorName = :old.tutorName

仅当'tutorName'值在新旧记录中相同时才返回true。当你试图更新一些值时,你会得到

IF 'someTutorName' = 'someTutorName' 

将返回TRUE。 插入行无法触发此规则,因为您正在尝试比较类似的内容:

'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;
/

但最好的解决方案是 friol 提到的那个 - 通过像这样执行SQL来使用唯一索引

ALTER TABLE tutors
ADD CONSTRAINT UNIQUE_TUTOR_NAME UNIQUE (tutorName);

答案 3 :(得分: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