我有这些表
CELL(CellId, x0, y0, x1, y1, CurrentPhone#, MaxCalls)
电话(电话号码, x, y, 电话状态)
STATE_CHANGE(ChangeId, TimeStamp, PhoneNo, x, y, ChangeType)
我必须创建这个触发器(触发器是强制性的)
更改活动呼叫的最大数量:蜂窝电话网络可以减少与单个蜂窝相关的最大活动呼叫数,以管理问题(减少 CELL 表中的 MaxCalls 值)。更新单个单元格的"最大呼叫"属性可能会导致不一致的情况,即 CELL 表中的"最大呼叫"值将小于所考虑的单元中当前处于活动状态的电话数 (PhoneState="活动")。如果是这样,则需要使用所考虑的单元格中当前处于活动状态的电话数(PhoneState='Active')更新相应的 MaxCalls 属性
我写了这个触发器
create or replace trigger CELL_T1
AFTER UPDATE OF MAXCALLS ON CELL
BEGIN
UPDATE CELL E1
SET E1.MAXCALLS=(
SELECT COO
FROM (SELECT E2.CELLID, COO
FROM CELL E2, (
SELECT CELLID, COUNT(*) COO
FROM CELL C2, TELEPHONE
WHERE PhoneState='Active' AND x<x1 AND x>=x0 AND y<y1 AND y>=y0
GROUP BY C2.CellId
)TW
WHERE E2.CELLID=TW.CELLID AND COO>E2.MAXCALLS
)
)
WHERE E1.CELLID IN (
SELECT C1.CELLID
FROM CELL C1, (
SELECT CELLID, COUNT(*) COO
FROM CELL C3, TELEPHONE
WHERE PhoneState='Active' AND x<x1 AND x>=x0 AND y<y1 AND y>=y0
GROUP BY C3.CellId
)TW1
WHERE C1.CELLID=TW1.CELLID AND COO>C1.MAXCALLS and e1.cellid=tw1.cellid
);
END;
触发器编译没有问题;然后我写了更新语句:
UPDATE CELL SET MAXCALLS=MAXCALLS-2;
但我收到这些错误:
ORA-06512: at "MATTEO.CELL_T1", line 2
ORA-04088: error during execution of trigger 'MATTEO.CELL_T1'
ORA-06512: at "MATTEO.CELL_T1", line 2
ORA-04088: error during execution of trigger 'MATTEO.CELL_T1'
ORA-06512: at "MATTEO.CELL_T1", line 2
ORA-04088: error during execution of trigger 'MATTEO.CELL_T1'
ORA-06512: at "MATTEO.CELL_T1", line 2
ORA-04088: error during execution of trigger 'MATTEO.CELL_T1'
ORA-06512: at "MATTEO.CELL_T1", line 2
ORA-04088: error during execution of trigger 'MATTEO.CELL_T1'
ORA-0
- 更新单元格
- 设置最大调用数 = 最大调用数-2;
我在触发器中找不到任何错误;出了什么问题?
问题很可能是您在这里进行递归更新。当您执行 UPDATE 时,触发器会执行另一个 UPDATE,这会触发触发器,该触发器会在永无止境的循环中执行另一个 UPDATE。直到,也就是说,甲骨文感到无聊并提出所有这些例外。
在这种情况下,实际上只有两条出路。
- 不要更新表并在视图(或其他内容)上使用代替 DML 触发器,以便触发器仅触发一次。
- 将所有这些逻辑删除到存储过程中,并且根本不使用触发器。
虽然我知道这个问题的原因(你的大学作业)不再相关。其他人可能仍然有一些类似的问题。
- 如果需要在触发器中进行一致性检查,请在更新之前进行,而不是之后。
- 仅检查语句实际修改的行。
- 对于此类操作,请使用 ROW 触发器,而不是 STATEMENT 触发器
- 使用":OLD"和":NEW"数据集,而不是查询表
所以做这样的事情(不在数据库中测试,只是动态编写)
CREATE OR REPLACE TRIGGER cell_t1
BEFORE UPDATE OF maxcalls ON cell
FOR EACH ROW
DECLARE
v_active_cnt NUMBER(20);
BEGIN
SELECT COUNT(*)
INTO v_active_cnt
FROM telephone
WHERE phonestate='Active'
AND x<:NEW.x1
AND x>=:NEW.x0
AND y<:NEW.y1
AND y>=:NEW.y0;
IF ( :NEW.maxcalls < v_active_cnt )
THEN
:NEW.maxcalls := v_active_cnt
END;
END;
这样做是 - 查询telephone
表中由当前修改的行标识的单元格中的活动电话数(:NEW 数据集) - 检查修改后的maxcalls
值是否大于此数字,如果是,请相应地修改新的maxcalls
值
顺便说一下,这正是这些触发器的用途。