Oracle 如何解决PLSQL/DELETE触发器错误中的此错误
我正在尝试用plsql编写一段代码,其功能如下: 在删除行之前,此触发器将检查该行是否有子行,如果是这样,子行将成为其祖父的子行,然后继续删除该行 所以,这就是我现在所拥有的:Oracle 如何解决PLSQL/DELETE触发器错误中的此错误,oracle,plsql,database-trigger,Oracle,Plsql,Database Trigger,我正在尝试用plsql编写一段代码,其功能如下: 在删除行之前,此触发器将检查该行是否有子行,如果是这样,子行将成为其祖父的子行,然后继续删除该行 所以,这就是我现在所拥有的: CREATE TABLE sucursal ( codsuc NUMBER (8) PRIMARY KEY, ganancia NUMBER (8) NOT NULL CHECK (ganancia > 0), sucpadre NUMBER (8) REFERENCES s
CREATE TABLE sucursal
(
codsuc NUMBER (8) PRIMARY KEY,
ganancia NUMBER (8) NOT NULL CHECK (ganancia > 0),
sucpadre NUMBER (8) REFERENCES sucursal
);
CREATE OR REPLACE TRIGGER borrar_sucursal
BEFORE DELETE
ON sucursal
FOR EACH ROW
WHEN (old.sucpadre IS NOT NULL)
BEGIN
DBMS_OUTPUT.PUT_LINE ('Bueno pues lo intente');
hijo_de_abuelo (:old.codsuc);
END;
/
CREATE OR REPLACE PROCEDURE hijo_de_abuelo (codigo IN sucursal.codsuc%TYPE)
IS
gato sucursal.sucpadre%TYPE;
BEGIN
SELECT sucpadre
INTO gato
FROM sucursal
WHERE codsuc = codigo;
FOR gallo IN (SELECT *
FROM sucursal
WHERE sucpadre = codigo)
LOOP
UPDATE sucursal
SET sucpadre = gato
WHERE codsuc = gallo.codsuc;
END LOOP;
END;
/
因此,当我尝试在SQL控制台中删除一行时,会发生以下情况:
SQL> delete from sucursal where codsuc = 2;
Bueno pues lo intente
delete from sucursal where codsuc = 2
*
ERROR at line 1:
ORA-04091: table PANCRACI0.SUCURSAL is mutating, trigger/function may not see
it
ORA-06512: at "PANCRACI0.HIJO_DE_ABUELO", line 7
ORA-06512: at "PANCRACI0.BORRAR_SUCURSAL", line 3
ORA-04088: error during execution of trigger 'PANCRACI0.BORRAR_SUCURSAL'
任何帮助都会很好。一个选项是编写一个过程来调用是否应该删除表中的行,而不是直接发出
DELETE
语句。在该过程中,在最终删除节点之前,首先重新定位子节点。但是,这可能需要您使用表更改应用程序
或者重命名该表以将其置于“背景”中
然后创建一个视图,其名称与重命名表之前的名称相同。这将视图保留在“前景”中
在该视图上,您现在可以放置一个而不是触发器来拦截删除s。触发器首先重新定位要删除的节点的子节点,然后删除“background”表中的节点
这样,您现有的代码仍然可以像以前一样使用该表。您正在选择并更新同一个表,这是“变异”,例如,请参阅
ALTER TABLE sucursal
RENAME TO sucursal_t;
CREATE VIEW sucursal
AS
SELECT codsuc,
ganancia,
sucpadre
FROM sucursal_t;
CREATE OR REPLACE TRIGGER borrar_sucursal
INSTEAD OF DELETE
ON sucursal
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('Bueno pues lo intente');
UPDATE sucursal_t
SET sucpadre = :old.sucpadre
WHERE sucpadre = :old.codsuc;
DELETE FROM sucursal_t
WHERE codsuc = :old.codsuc;
END;
/