我遇到以下代码问题,这是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');
答案 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)
现在可以在下面进行实时测试