所以我试图使用触发器基本上设置一些规则..如果任何人的身份证号码低于3,他将只需支付100美元,但如果某人的身份证号码高于此值,他将不得不支付更多。我做了一些研究,并被告知使用触发器,并且在获取多行时触发器非常有用。所以我尝试过这样做,但它没有奏效。基本上触发器被创建但是当我尝试添加值时,我收到以下错误: -
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "S.PRICTICKET", line 6
ORA-04088: error during execution of trigger 'S.PRICTICKET'
这是我做触发器所做的: -
CREATE OR REPLACE TRIGGER PRICTICKET BEFORE INSERT OR UPDATE OR DELETE ON PAYS FOR EACH ROW ENABLE
DECLARE
V_PRICE PAYS.PRICE%TYPE;
V_ID PAYS.ID%TYPE;
V_NAME PAYS.NAME%TYPE;
BEGIN
SELECT ID,NAME INTO V_ID,V_NAME FROM PAYS;
IF INSERTING AND V_ID<3 THEN
V_PRICE:=100;
INSERT INTO PAYS(ID,NAME,PRICE) VALUES (V_ID,V_NAME,V_PRICE);
ELSIF INSERTING AND V_ID>=3 THEN
V_PRICE:=130;
INSERT INTO PAYS(ID,NAME,PRICE) VALUES (V_ID,V_NAME,V_PRICE);
END IF;
END;
事情是,当我执行这段代码时,我确实得到一条消息说已经编译了触发器。但是当我尝试使用以下代码将值插入表中时,我收到上面提到的错误消息。
INSERT INTO PAYS(ID,NAME) VALUES (19,'SS');
答案 0 :(得分:1)
您收到了指定的错误ORA-01422
,因为您使用以下SELECT
返回了多行:
SELECT ID,NAME INTO V_ID,V_NAME FROM PAYS;
您需要限制结果集。例如,我将使用:NEW
psuedorecord来获取行的新ID值,如果唯一,则会将SELECT
限制为一行:
SELECT ID,NAME INTO V_ID,V_NAME FROM PAYS WHERE ID = :NEW.ID;
以下是有关使用触发器的Oracle文档:https://docs.oracle.com/database/121/TDDDG/tdddg_triggers.htm#TDDDG99934
但是,我认为您的触发器还有其他问题,请参阅我的评论,我们可以讨论。
编辑:根据我们的讨论。
ORA-04088:执行触发器时出错
在同一个表的INSERT
触发器中使用BEFORE INSERT
将创建一个无限循环。请考虑使用AFTER INSERT
并将INSERTS
更改为UPDATES
或INSTEAD OF INSERT
。
此外,从触发器定义中删除DELETE
。在这种情况下,这没有任何意义。
答案 1 :(得分:1)
让我们开始清理一些事情。你被告知&#34;触发器在获取多行时非常有用&#34;这是一般规则,没有额外的背景,是错误的。有4种类型的DML触发器: 语句之前 - 无论处理的行数是多少,都会为语句触发1次。 行前 - 在语句中处理的每一行触发一次,然后将旧值和新值合并为一组值。此时,您可以更改列中的值。 行后 - 在将旧值和新值合并为一组值后,在语句中处理的行触发一次。此时,您无法更改列值。 语句后 - 无论处理的行数是多少,都会为语句触发一次。
请记住,触发器实际上是声明的一部分。
可以为插入,更新或删除触发触发器。但是,没有必要对每个人开火。在这种情况下,建议删除删除。但是更新作为你的触发器没有做任何事情。 (注意:有复合触发器,但它们包含上述每一个的段)。
通常,触发器无法引用触发它的表。请参阅错误ORA-04091。
如果您在插入时触发了触发器无法在同一个表中插入(也请参阅ORA-04091),即使您绕过该插入会触发触发器,创建一个递归的,也许是一个永无止境的循环 - 这将在这里发生。
使用:新建。 column_name 和:旧。 column_name 以适当引用列值。不要试图选择它们。
由于您试图确定列的值,因此必须使用Before触发器。
因此将此应用于您的触发器,结果将变为:
CREATE OR REPLACE TRIGGER PRICTICKET
BEFORE INSERT ON PAYS
FOR EACH ROW ENABLE
BEGIN
if :new.id is not null
if :new.ID<3 then
:new.Price :=100;
else
:new.Price := 130;
end if ;
else
null; -- what should happen here?
end if ;
END PRICTICKET ;