1

我在下面的代码中遇到问题,这是 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;
/

此触发器用于防止用户在不同的记录中输入相同的导师姓名。

在我插入两条具有相同导师姓名的记录后,触发器不会阻止我插入它。有没有人可以告诉我这个编码有什么问题?以下是示例格式和插入值:

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

4 回答 4

4

在 Kamil 的例子中 Trigger 会抛出ORA-04091 ,你可以在这里亲眼看到。触发器中的 ROLLBACK 是不必要的,当触发器使语句失败时它会隐式运行。

您可以通过使用只读子句更改表来禁止表上的任何 DML :

alter table tutors read only;

最后,完整性应该用完整性约束而不是触发器来声明。

祝你好运!

于 2013-07-15T11:24:37.463 回答
1

您不需要在 Oracle 中为此设置触发器。

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

注意:关于您的触发器,它无法检查具有相同导师名称的另一条记录,因为它没有扫描导师表以查找具有相同导师名称的另一条记录,它只是比较您正在创建的行的导师名称值(在这种情况下,旧.tutorName 只是 NULL,因为该行还不存在)。

于 2013-07-14T16:27:37.823 回答
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);
于 2013-07-14T16:38:25.827 回答
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

于 2017-07-26T12:55:41.607 回答