ORA-22903: выражение MULTISET запрещено - PullRequest
0 голосов
/ 02 января 2019

У меня есть таблица с полем в виде вложенной таблицы. У меня есть триггер в первой таблице, но он не работает и приводит к: ORA-22903: выражение MULTISET не разрешено

CREATE OR REPLACE TYPE DIA_T as object
(dia varchar2(9),
hora varchar2(6));


CREATE OR REPLACE TYPE DIA_TAB IS TABLE OF DIA_T;


CREATE TABLE T_TALLER(
PK NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
...
DIAS DIA_TAB,
FEC_INI DATE NOT NULL,
FEC_FIN DATE NOT NULL,
...
CONSTRAINT CST_PRIMKEY_TALLER PRIMARY KEY (PK),
...
) NESTED TABLE DIAS STORE AS DIAS_TAB;

Мой триггер:

CREATE OR REPLACE TRIGGER TRG_TALLER_AU_FEC_FIN AFTER UPDATE OF FEC_FIN ON T_TALLER FOR EACH ROW
BEGIN

FOR REC IN (SELECT T.DIA , T.HORA                
            FROM TABLE(:NEW.DIAS) T) LOOP

    dbms_output.put_line(REC.DIA||' '||REC.HORA);


END LOOP;

END;

Когда я пытаюсь что-то подобное:

update t_taller set fec_fin = fec_fin + 20 where pk = 10;

Я получаю следующую ошибку:

    ORA-22903: MULTISET expression not allowed
    ORA-06512: at "ESTAMPAS.TRG_TALLER_AU_FEC_FIN", line 3
    ORA-04088: error during execution of trigger 'ESTAMPAS.TRG_TALLER_AU_FEC_FIN'

Можете ли вы помочь мне решить эту проблему?

Заранее спасибо. С уважением,

UPDATE

Триггер, который я разместил, является фиктивным, но ошибка, которую я получаю для реального, такая же, мой настоящий триггер это

CREATE OR REPLACE TRIGGER TRG_TALLER_AU_FEC_FIN AFTER UPDATE OF FEC_FIN ON T_TALLER FOR EACH ROW
BEGIN

IF :NEW.FEC_FIN >= :OLD.FEC_FIN THEN

    Pkg_Utilidades.p_ins_taller_clase_grupo(:NEW.PK,(:OLD.FEC_FIN) + 1,:NEW.FEC_FIN,:NEW.DIAS,:NEW.AU_USU_INS);

ELSE

    DELETE T_TALLER_CLASE
    WHERE FK_TALLER = :NEW.PK
    AND FEC_CLASE BETWEEN :NEW.FEC_FIN + 1 AND :OLD.FEC_FIN;


END IF;

END;

Что-то еще сказать, у меня есть триггер "ПОСЛЕ ВСТАВКИ", и он отлично работает:

CREATE OR REPLACE TRIGGER TRG_TALLER_AI_CLASE AFTER INSERT ON T_TALLER FOR EACH ROW
BEGIN

DELETE T_TALLER_CLASE WHERE FK_TALLER = :NEW.PK;

Pkg_Utilidades.p_ins_taller_clase_grupo(:NEW.PK,:NEW.FEC_INI,:NEW.FEC_FIN,:NEW.DIAS,:NEW.AU_USU_INS);


END;

Процедура:

PROCEDURE p_ins_taller_clase_grupo (p_taller NUMBER,
                                p_fec_ini DATE,
                                p_fec_fin DATE,
                                p_dias DIA_TAB,
                                p_user VARCHAR2) IS
p_output VARCHAR2(100);  
v_dia NUMBER;
BEGIN

FOR REC IN (SELECT p_fec_ini + LEVEL - 1 FECHA,
            DECODE(TO_CHAR(p_fec_ini + LEVEL - 1 , 'DAY'),'MONDAY   ',1,'TUESDAY  ',2,'WEDNESDAY',3,'THURSDAY ',4,'FRIDAY   ',5,'SATURDAY ',6,7) DIA
            FROM DUAL
            CONNECT BY LEVEL <= p_fec_fin - p_fec_ini  + 1) LOOP

    BEGIN

        SELECT D INTO v_dia
        FROM (
            SELECT decode(upper(T.dia),'LUNES',1,'MARTES',2,'MIERCOLES',3,'MIÉRCOLES',3,'JUEVES',4,'VIERNES',5,'SABADO',6,'SÁBADO',6,7) D                
            FROM TABLE(p_dias) T
            )             
        WHERE D = REC.DIA;

        P_INS_TALLER_CLASE (p_taller,REC.FECHA,Pkg_conf.CST_HORA,p_user,p_output);

    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            NULL;
    END;



END LOOP;


END p_ins_taller_clase_grupo;                                   

Вставка Работает нормально:

SQL> insert into t_taller (FK_profesor,fk_danza,fk_local,fk_periodicidad,fec_ini,fec_fin,dias,AU_USU_INS) values (1,1,1,1,to_date('05/01/2019','dd/mm/yyyy'),to_date('27/01/2019','dd/mm/yyyy'),dia_tab(dia_t('SABADO','10:30'),dia_t('DOMINGO','10:30')),'EP_PL01');

1 row created.

SQL> commit;

Commit complete.

SQL> update t_taller set fec_fin = fec_fin + 20 where pk = 24;
update t_taller set fec_fin = fec_fin + 20 where pk = 24
       *
ERROR at line 1:
ORA-22903: MULTISET expression not allowed
ORA-06512: at "ESTAMPAS.PKG_UTILIDADES", line 451
ORA-06512: at "ESTAMPAS.TRG_TALLER_AU_FEC_FIN", line 5
ORA-04088: error during execution of trigger 'ESTAMPAS.TRG_TALLER_AU_FEC_FIN'

Строка 451 пакета находится внутри процедуры, именно здесь:

        SELECT D INTO v_dia
        FROM (
            SELECT decode(upper(T.dia),'LUNES',1,'MARTES',2,'MIERCOLES',3,'MIÉRCOLES',3,'JUEVES',4,'VIERNES',5,'SABADO',6,'SÁBADO',6,7) D                
            FROM TABLE(p_dias) T
            )             
        WHERE D = REC.DIA;

Извините, что не выложил все детали с самого начала, я хотел обобщить и показать только ошибку.

Привет

Ответы [ 2 ]

0 голосов
/ 02 января 2019

TABLE выражение работает, если вы выполняете запрос на выборку для самой таблицы.

Что-то вроде

SELECT T.DIA , T.HORA                
            FROM T_TALLER ,TABLE(:NEW.DIAS) T

Но вы не можете выбирать из владельца Trigger какэто приводит к ошибке «таблица мутируется» ( ORA-04091 ).

Вместо этого вы можете перебрать столбец вложенной таблицы, используя простой for loop.

CREATE OR REPLACE TRIGGER trg_taller_au_fec_fin AFTER
     UPDATE OF fec_fin ON t_taller
     FOR EACH ROW
BEGIN
     FOR i in 1 .. :new.dias.count
     LOOP
          dbms_output.put_line(:new.dias(i).dia || ' ' || :new.dias(i).hora);
     END LOOP;
END;
/

Кстати, как уже упоминалось @XING, в триггере нет смысла dbms_output.Скорее всего, стоит занести их в таблицу.

Демо

0 голосов
/ 02 января 2019

Как уже упоминалось в моих комментариях Triggers используются для обработки событий на столе в.Хотя ваш опубликованный сценарий не имеет особого смысла для меня, однако я даю решение.Также вы просто не можете Select записи из Nested таблицы.Вам нужно использовать оператор таблицы, чтобы сделать это.Также в триггере, если вы выберете «Выбрать» на той же таблице, вы можете попасть на mutating, trigger/function.См. Ниже демо:

CREATE OR REPLACE TYPE dia_t AS OBJECT (
    dia    VARCHAR2(9),
    hora   VARCHAR2(6)
);


CREATE OR REPLACE TYPE DIA_TAB IS TABLE OF DIA_T;

CREATE TABLE t_taller (
    pk        NUMBER   ,
    dias      dia_tab,
    fec_ini   DATE NOT NULL,
    fec_fin   DATE NOT NULL,
    CONSTRAINT cst_primkey_taller PRIMARY KEY ( pk )
)
NESTED TABLE dias STORE AS dias_tab;

INSERT INTO t_taller VALUES (
    1,
    dia_tab(dia_t(
        'A',
        'B')
    ),
    TO_DATE('10-Dec-2018','DD-Mon-YYYY'),
    TO_DATE('10-Dec-2018','DD-Mon-YYYY')
);

CREATE OR REPLACE TRIGGER trg_taller_au_fec_fin 
AFTER UPDATE OF fec_fin ON t_taller
FOR EACH ROW
BEGIN
    FOR rec IN ( SELECT t.dia,
                        t.hora
                 FROM  t_taller e,TABLE (e.dias ) t) --This is how you select records from nested table 
    LOOP
        dbms_output.put_line(rec.dia || ' ' || rec.hora);
    END LOOP;
END;

Вывод:

Error starting at line : 40 in command -
update t_taller set fec_fin = fec_fin + 20 where pk = 1
Error report -
ORA-04091: table SYSTM.T_TALLER is mutating, trigger/function may not see it
ORA-06512: at "SYSTM.TRG_TALLER_AU_FEC_FIN", line 2
ORA-04088: error during execution of trigger 'SYSTM.TRG_TALLER_AU_FEC_FIN'

Итак, вам снова нужно пересмотреть свое требование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...