我有三张桌子,电影,展览和房间。我想在一个给定的房间里插入一部电影的新节目,我想如果没有时间和那些离开的电影发生碰撞,我可以用扳机来做这些傻事。
我写了这个:
CREATE OR REPLACE TRIGGER insert_new_show
BEFORE INSERT ON show
FOR EACH ROW
DECLARE
-- pragma autonomous_transaction;
collisioni varchar(40);
runtime INT;
error1 EXCEPTION;
error2 EXCEPTION;
BEGIN
IF :new.time < CURRENT_TIMESTAMP THEN
RAISE error1;
END IF;
SELECT runtime INTO runtime
FROM film
WHERE title = deref(:new.di_film).title;
SELECT film.title INTO collisioni
FROM show JOIN film ON deref(show.di_film).title=film.title
WHERE DEREF(room).nome = DEREF(:NEW.room).nome
AND ( (:new.time < show.time AND :new.time + runtime + 10 > show.time)
OR (:new.time > show.time
AND :new.time < show.time + runtime + 10));
IF NOT SQL%NOTFOUND THEN
INSERT INTO show
SELECT to_timestamp(:NEW.orario,'yyyy-mm-dd hh24:mi:ss')
, :NEW.max_n_spot,:NEW.costo, REF(s), NULL, REF(f)
FROM film f, room s
WHERE f.title=deref(:NEW.di_film).title
AND s.nome=deref(:NEW.room).nome;
ELSE
RAISE error2;
END IF;
EXCEPTION
WHEN error1 THEN
RAISE_APPLICATION_ERROR(-20491,'Error');
WHEN error2 THEN
RAISE_APPLICATION_ERROR(-20491,'Error');
END;如果我不使用“语用autonomous_transaction",我就会得到一个table s%s is mutating错误。但是,当然,对于事务,触发器不能看到:new值。我还想用检查约束来做检查,但我不知道它是否有效。你能帮我找到解决办法吗?
发布于 2012-11-02 13:47:50
这是典型的“使用包/过程”的情况。
当您在当前正在对其执行DML操作的触发器中查询表时,您将获得ORA-04091: table name is mutating, trigger/function may not see it。Oracle不允许这样做,为了维护数据的读一致视图,有多种方法可以避免这种情况,其中大多数涉及尝试做一些稍微古怪的事情;包括您已经注意到的自主事务。
然而,它们并不影响错误的根本原因;也就是说,您正在做一些错误的事情。此错误通常表示两种情况中的一种或两种:
解决方案是将逻辑移到包或过程中,这具有删除一层混淆和辅助调试的额外好处。
在这里,我看不出检查约束是如何实现的,因为您仍然需要知道胶片中的运行时,这需要查询第二个表。
进一步读:
https://stackoverflow.com/questions/13195887
复制相似问题