用于计算嵌套 table 内属性的 Oracle 触发器
Oracle trigger for calculating an attribute inside nested table
我有一个 table (Compra) 和一个嵌套的 table 在里面 (lineasCompra)。有那些tables的结构:
CREATE OR REPLACE TYPE Linea_Compra_ntabtyp AS TABLE OF Linea_Compra_ObjTyp;
CREATE OR REPLACE TYPE Compra_ObjTyp AS OBJECT (
num_compra NUMBER(8),
fecha_compra DATE,
precio_totalc NUMBER(5,2),
lineasCompra Linea_Compra_ntabtyp,
Usuario REF Usuario_ObjTyp,
Pago lista_Ref_Pago,
);
CREATE OR REPLACE TYPE Linea_Compra_ObjTyp AS OBJECT(
id_lcompra NUMBER(8),
puc NUMBER(5,2),
iva NUMBER(3,2),
pvp NUMBER(5,2),
Juego REF Juego_ObjTyp,
);
情况是,对于 LineasCompra 中的每一行,我希望触发器计算 pvp = puc * (1+iva) .
为此,我得到了 Compras 与 table Compra 相同的观点。这就是我试过的:
备注:
- Act_IVACompra 用于 table Compra,而 Act_IVACompra _N 用于嵌套 table.*
- VPT是Compratable上的precio_total属性,是所有嵌套table的pvp的加法。
- PT 是嵌套 table
中 pvp 的时间变量
--for the main table
CREATE OR REPLACE TRIGGER Act_IvaCompra
INSTEAD OF INSERT OR UPDATE ON Compras
FOR EACH ROW
DECLARE
VPT NUMBER;
I BINARY_INTEGER;
BEGIN
IF :NEW.lineasCompra IS NOT NULL THEN
VPT := 0;
FOR I IN 1..:NEW.lineasCompra.COUNT LOOP
VPT := VPT + :NEW.lineasCompra(I).pvp;
END LOOP;
ELSE
VPT := 0;
END IF;
IF INSERTING THEN
INSERT INTO COMPRA_OBJTAB
VALUES (:NEW.num_compra, :NEW.fecha_compra, VPT, :NEW.lineasCompra, :NEW.USUARIO, :NEW.PAGO);
END IF;
IF UPDATING THEN
UPDATE COMPRA_OBJTAB SET num_compra = :NEW.num_compra, fecha_compra = :NEW.fecha_compra, precio_totalc = VPT, lineasCompra = :NEW.lineasCompra, Usuario = :NEW.Usuario, Pago = :NEW.Pago
WHERE num_compra = :OLD.num_compra;
END IF;
END;
--for the nested table
CREATE OR REPLACE TRIGGER Act_IVACompra_N
INSTEAD OF INSERT OR UPDATE
ON NESTED TABLE lineasCompra OF Compras
FOR EACH ROW
DECLARE
PT NUMBER;
BEGIN
PT := :NEW.puc*(1+:NEW.iva);
IF INSERTING THEN
INSERT INTO TABLE (SELECT lineasCompra FROM COMPRA_OBJTAB WHERE num_compra = :PARENT.num_compra)
VALUES (:NEW.id_lcompra, :NEW.puc, :NEW.iva, PT, :NEW.Juego);
END IF;
IF UPDATING THEN
UPDATE TABLE (SELECT lineasCompra FROM COMPRA_OBJTAB WHERE num_compra = :PARENT.num_compra)
SET id_lcompra = :NEW.id_lcompra, puc = :NEW.puc, iva = :NEW.iva, pvp = PT, Juego = :NEW.Juego
WHERE id_lcompra = :NEW.id_lcompra;
END IF;
END;
我试过的插入方式是:
INSERT INTO Compras VALUES (14,'04-03-2021',NULL ,Linea_Compra_nTabTyp(Linea_Compra_ObjTyp(1,13.00,0.21,NULL,
(SELECT REF(J) FROM Juego_ObjTab J WHERE ID=1))),
(SELECT REF(U) FROM Usuario_ObjTab U WHERE id_usuario=1),
(SELECT CAST(COLLECT(REF(P)) AS lista_Ref_Pago) FROM Pago_ObjTab P));
其中 NULL 值指的是 precio_total (VPT) 和 pvp (PT)。
我从插入中得到的结果是,precio_total 和 pvp 都没有被计算(均为 NULL)。
这可能是一个愚蠢的问题,但我无法检测到问题出在哪里。非常感谢。
编辑后添加了一些代码
CREATE TABLE Compra_ObjTab OF Compra_ObjTyp (
num_compra PRIMARY KEY,
fecha_compra NOT NULL,
CHECK (precio_totalc >= 0)
) NESTED TABLE lineasCompra STORE AS Lineas_Compra_ntab ((PRIMARY KEY(nested_table_id, id_lcompra),
CHECK (puc >= 0),
CHECK (iva >= 0),
CHECK (pvp > 0)))
NESTED TABLE Pago STORE AS pagoc_ref_objtab;
ALTER TABLE Lineas_Compra_ntab ADD (SCOPE FOR (Juego) IS Juego_ObjTab);
CREATE OR REPLACE VIEW Compras AS
SELECT * FROM Compra_ObjTab;
在你插入的 pvp 是空的,所以只需添加 NVL():
dbms_output 添加只是为了显示调试:
--for the main table
CREATE OR REPLACE TRIGGER Act_IvaCompra
INSTEAD OF INSERT OR UPDATE ON Compras
FOR EACH ROW
DECLARE
VPT NUMBER;
I BINARY_INTEGER;
lpn Linea_Compra_ObjTyp;
l_puc NUMBER(5,2);
l_iva NUMBER(3,2);
BEGIN
dbms_output.put_line('Act_IvaCompra');
dbms_output.put_line(:NEW.lineasCompra.COUNT);
IF :NEW.lineasCompra IS NOT NULL THEN
dbms_output.put_line('not null');
VPT := 0;
FOR I IN 1..:NEW.lineasCompra.COUNT LOOP
lpn := :NEW.lineasCompra(I);
dbms_output.put_line('puc:'||lpn.puc);
dbms_output.put_line('iva:'||lpn.iva);
dbms_output.put_line('pvp:'||lpn.pvp);
VPT := VPT + nvl(:NEW.lineasCompra(I).pvp, :NEW.lineasCompra(I).puc*(1+:NEW.lineasCompra(I).iva));
dbms_output.put_line('loop i:'||i||', VPT='||VPT);
END LOOP;
ELSE
dbms_output.put_line('null - VPT = 0');
VPT := 0;
END IF;
IF INSERTING THEN
INSERT INTO COMPRA_OBJTAB
VALUES (:NEW.num_compra, :NEW.fecha_compra, VPT, :NEW.lineasCompra, :NEW.USUARIO, :NEW.PAGO);
END IF;
IF UPDATING THEN
UPDATE COMPRA_OBJTAB SET num_compra = :NEW.num_compra, fecha_compra = :NEW.fecha_compra, precio_totalc = VPT, lineasCompra = :NEW.lineasCompra, Usuario = :NEW.Usuario, Pago = :NEW.Pago
WHERE num_compra = :OLD.num_compra;
END IF;
END;
/
我有一个 table (Compra) 和一个嵌套的 table 在里面 (lineasCompra)。有那些tables的结构:
CREATE OR REPLACE TYPE Linea_Compra_ntabtyp AS TABLE OF Linea_Compra_ObjTyp;
CREATE OR REPLACE TYPE Compra_ObjTyp AS OBJECT (
num_compra NUMBER(8),
fecha_compra DATE,
precio_totalc NUMBER(5,2),
lineasCompra Linea_Compra_ntabtyp,
Usuario REF Usuario_ObjTyp,
Pago lista_Ref_Pago,
);
CREATE OR REPLACE TYPE Linea_Compra_ObjTyp AS OBJECT(
id_lcompra NUMBER(8),
puc NUMBER(5,2),
iva NUMBER(3,2),
pvp NUMBER(5,2),
Juego REF Juego_ObjTyp,
);
情况是,对于 LineasCompra 中的每一行,我希望触发器计算 pvp = puc * (1+iva) .
为此,我得到了 Compras 与 table Compra 相同的观点。这就是我试过的:
备注:
- Act_IVACompra 用于 table Compra,而 Act_IVACompra _N 用于嵌套 table.*
- VPT是Compratable上的precio_total属性,是所有嵌套table的pvp的加法。
- PT 是嵌套 table 中 pvp 的时间变量
--for the main table
CREATE OR REPLACE TRIGGER Act_IvaCompra
INSTEAD OF INSERT OR UPDATE ON Compras
FOR EACH ROW
DECLARE
VPT NUMBER;
I BINARY_INTEGER;
BEGIN
IF :NEW.lineasCompra IS NOT NULL THEN
VPT := 0;
FOR I IN 1..:NEW.lineasCompra.COUNT LOOP
VPT := VPT + :NEW.lineasCompra(I).pvp;
END LOOP;
ELSE
VPT := 0;
END IF;
IF INSERTING THEN
INSERT INTO COMPRA_OBJTAB
VALUES (:NEW.num_compra, :NEW.fecha_compra, VPT, :NEW.lineasCompra, :NEW.USUARIO, :NEW.PAGO);
END IF;
IF UPDATING THEN
UPDATE COMPRA_OBJTAB SET num_compra = :NEW.num_compra, fecha_compra = :NEW.fecha_compra, precio_totalc = VPT, lineasCompra = :NEW.lineasCompra, Usuario = :NEW.Usuario, Pago = :NEW.Pago
WHERE num_compra = :OLD.num_compra;
END IF;
END;
--for the nested table
CREATE OR REPLACE TRIGGER Act_IVACompra_N
INSTEAD OF INSERT OR UPDATE
ON NESTED TABLE lineasCompra OF Compras
FOR EACH ROW
DECLARE
PT NUMBER;
BEGIN
PT := :NEW.puc*(1+:NEW.iva);
IF INSERTING THEN
INSERT INTO TABLE (SELECT lineasCompra FROM COMPRA_OBJTAB WHERE num_compra = :PARENT.num_compra)
VALUES (:NEW.id_lcompra, :NEW.puc, :NEW.iva, PT, :NEW.Juego);
END IF;
IF UPDATING THEN
UPDATE TABLE (SELECT lineasCompra FROM COMPRA_OBJTAB WHERE num_compra = :PARENT.num_compra)
SET id_lcompra = :NEW.id_lcompra, puc = :NEW.puc, iva = :NEW.iva, pvp = PT, Juego = :NEW.Juego
WHERE id_lcompra = :NEW.id_lcompra;
END IF;
END;
我试过的插入方式是:
INSERT INTO Compras VALUES (14,'04-03-2021',NULL ,Linea_Compra_nTabTyp(Linea_Compra_ObjTyp(1,13.00,0.21,NULL,
(SELECT REF(J) FROM Juego_ObjTab J WHERE ID=1))),
(SELECT REF(U) FROM Usuario_ObjTab U WHERE id_usuario=1),
(SELECT CAST(COLLECT(REF(P)) AS lista_Ref_Pago) FROM Pago_ObjTab P));
其中 NULL 值指的是 precio_total (VPT) 和 pvp (PT)。
我从插入中得到的结果是,precio_total 和 pvp 都没有被计算(均为 NULL)。
这可能是一个愚蠢的问题,但我无法检测到问题出在哪里。非常感谢。
编辑后添加了一些代码
CREATE TABLE Compra_ObjTab OF Compra_ObjTyp (
num_compra PRIMARY KEY,
fecha_compra NOT NULL,
CHECK (precio_totalc >= 0)
) NESTED TABLE lineasCompra STORE AS Lineas_Compra_ntab ((PRIMARY KEY(nested_table_id, id_lcompra),
CHECK (puc >= 0),
CHECK (iva >= 0),
CHECK (pvp > 0)))
NESTED TABLE Pago STORE AS pagoc_ref_objtab;
ALTER TABLE Lineas_Compra_ntab ADD (SCOPE FOR (Juego) IS Juego_ObjTab);
CREATE OR REPLACE VIEW Compras AS
SELECT * FROM Compra_ObjTab;
在你插入的 pvp 是空的,所以只需添加 NVL(): dbms_output 添加只是为了显示调试:
--for the main table
CREATE OR REPLACE TRIGGER Act_IvaCompra
INSTEAD OF INSERT OR UPDATE ON Compras
FOR EACH ROW
DECLARE
VPT NUMBER;
I BINARY_INTEGER;
lpn Linea_Compra_ObjTyp;
l_puc NUMBER(5,2);
l_iva NUMBER(3,2);
BEGIN
dbms_output.put_line('Act_IvaCompra');
dbms_output.put_line(:NEW.lineasCompra.COUNT);
IF :NEW.lineasCompra IS NOT NULL THEN
dbms_output.put_line('not null');
VPT := 0;
FOR I IN 1..:NEW.lineasCompra.COUNT LOOP
lpn := :NEW.lineasCompra(I);
dbms_output.put_line('puc:'||lpn.puc);
dbms_output.put_line('iva:'||lpn.iva);
dbms_output.put_line('pvp:'||lpn.pvp);
VPT := VPT + nvl(:NEW.lineasCompra(I).pvp, :NEW.lineasCompra(I).puc*(1+:NEW.lineasCompra(I).iva));
dbms_output.put_line('loop i:'||i||', VPT='||VPT);
END LOOP;
ELSE
dbms_output.put_line('null - VPT = 0');
VPT := 0;
END IF;
IF INSERTING THEN
INSERT INTO COMPRA_OBJTAB
VALUES (:NEW.num_compra, :NEW.fecha_compra, VPT, :NEW.lineasCompra, :NEW.USUARIO, :NEW.PAGO);
END IF;
IF UPDATING THEN
UPDATE COMPRA_OBJTAB SET num_compra = :NEW.num_compra, fecha_compra = :NEW.fecha_compra, precio_totalc = VPT, lineasCompra = :NEW.lineasCompra, Usuario = :NEW.Usuario, Pago = :NEW.Pago
WHERE num_compra = :OLD.num_compra;
END IF;
END;
/