用于计算嵌套 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 相同的观点。这就是我试过的:

备注:

--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_totalpvp 都没有被计算(均为 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;
/