简体   繁体   English

Oracle SQL触发器

[英]Oracle SQL Trigger

I want to prevent the database from storing any values bigger than 20 into a table. 我想防止数据库将任何大于20的值存储到表中。

CREATE OR REPLACE TRIGGER Dont_Allow
AFTER INSERT ON Cities
FOR EACH ROW

WHEN (new.IDCity > 20)

BEGIN
   dbms_output.put_line('  Failed to insert ' || :new.IDCity);
   delete from orase where IDCity=:new.IDCity;
END;

While this does work in terms of not actually adding anything with an ID > 20 , every time the trigger tries to do its magic, this shows up: 尽管这样做的确有效,实际上并没有添加任何ID > 20东西,但是每次触发器尝试执行其魔术操作时,这都会显示:

ORA-04091: table SYSTEM.ORASE is mutating, trigger/function may not see it ORA-04091:表SYSTEM.ORASE正在变异,触发器/函数可能看不到它
ORA-06512: at "SYSTEM.DONT_ALLOW", line 6 ORA-06512:位于“ SYSTEM.DONT_ALLOW”的第6行
ORA-04088: error during execution of trigger 'SYSTEM.DONT_ALLOW' ORA-04088:执行触发器'SYSTEM.DONT_ALLOW'时出错

What's a proper way of doing what I want? 什么是做我想要的正确方法?


EDIT: 编辑:

I've decided to use a trigger for this: 我决定为此使用触发器:

After a new row is inserted into Employees , a trigger checks the new guy's salary and if it's above 21 units / hour, it takes 5% off management's bonus. Employees插入新行后,触发器将检查新Employees的薪水,如果薪水高于21个单位/小时,则将获得5%的管理层奖金。 Lame, but hey - I'm using a trigger to solve a problem I don't have: the outcome won't be pretty. me脚,但是,嘿-我正在使用触发器来解决我没有的问题:结果不会很漂亮。

CREATE OR REPLACE TRIGGER Bite_Bonus
AFTER INSERT ON Employees
FOR EACH ROW

WHEN (new.HourSalary > 20)

BEGIN
   update Management set Bonus = Bonus - 5/100 * Bonus;
END;

You shouldn't be using a TRIGGER for that, you should be using a CHECK , like CONSTRAINT city_id_below_20 CHECK (IDCity < 20) . 您不应该为此使用TRIGGER ,而应使用CHECK ,例如CONSTRAINT city_id_below_20 CHECK (IDCity < 20) You can use ALTER TABLE ADD CONSTRAINT to put it on an existing table. 您可以使用ALTER TABLE ADD CONSTRAINT将其放在现有表上。

As TC1 indicated, the proper way to enforce this sort of requirement is to use a constraint. 如TC1所示,强制执行此类要求的正确方法是使用约束。

If you are forced to use the inferior approach because this is a school assignment, you most likely want to raise an exception in your trigger 如果由于这是一次学校作业而被迫使用劣等方法,那么您很可能想在触发器中引发异常

CREATE OR REPLACE TRIGGER Dont_Allow
  BEFORE INSERT OR UPDATE ON Cities
  FOR EACH ROW
  WHEN (new.IDCity > 20)
BEGIN
  RAISE_APPLICATION_ERROR( -20001, 'IDCity cannot exceed 20 so rejecting invalid value: ' || :new.IDCity );
END;

If you need to use a trigger for this, make it a BEFORE INSERT trigger, not an AFTER INSERT - you don't want that insert to happen at all. 如果您需要为此使用触发器,请将其设置为BEFORE INSERT触发器,而不是AFTER INSERT您根本不希望该插入发生。 Trying to "undo" it after the fact is not a good approach. 在事实发生后尝试“撤消”它不是一个好方法。

To abort the insert, all you need to do is raise an exception within that trigger. 要中止插入,您要做的就是在该触发器内引发异常。 Probably the best thing for this is to raise an application error . 可能最好的办法是引发应用程序错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM