I am fairly new to the oracle forms. I have a requirement of using the json_table function. When i run the below query I get the error message mentioned below. But when I run the same query in sql developer it works. Would be great if someone could help me find out the rootcause for the same. Thank you.
SELECT RPTD.GROUP_TODO_ID,
query_json.event_id
into :GLOBAL.RVS_ID,:GLOBAL.RV_EV_ID
FROM RGTD ,
RPTD
,json_table(RGTD.REVSHARE_INFO, '$' COLUMNS ( NESTED PATH '$.revenueShareFunds[*]' COLUMNS ( ID
VARCHAR2(10) PATH '$.rapId' , EVENT_ID VARCHAR2(12) PATH '$.revenueShareEventId')))
query_json
WHERE QUERY_JSON.ID = 'xxxxx'
AND RGTD.ID = RPTD.GROUP_TODO_ID
AND rownum =1;
Error I get while compiling the 12c oracle forms :
Compiling PRE-QUERY trigger on REVSHARE_PART_TO_DO data block...
Compilation error on PRE-QUERY trigger on REVSHARE_PART_TO_DO data block:
PL/SQL ERROR 103 at line 23, column 95
Encountered the symbol ";" when expecting one of the following:
) , * & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
The symbol ")" was substituted for ";" to continue.
For the recent versions of Forms(10,11), even the explicit join was not possible within the forms. So, you rather can put the query into a stored procedure within the DB such as
CREATE OR REPLACE PROCEDURE Get_ID_Values(
i_json_id IN VARCHAR2,
o_rvs_id OUT rptd.group_todo_id%type,
o_rv_ev_id OUT VARCHAR2,
o_error OUT VARCHAR2
)
AS
BEGIN
SELECT rptd.group_todo_id, query_json.event_id
INTO o_rvs_id, o_rv_ev_id
FROM rgtd
JOIN rptd
ON rgtd.id = rptd.group_todo_id
CROSS JOIN json_table(rgtd.revshare_info,
'$' COLUMNS(NESTED PATH '$.revenueShareFunds[*]'
COLUMNS(id VARCHAR2(10) PATH '$.rapId',
event_id VARCHAR2(12) PATH
'$.revenueShareEventId'))) query_json
WHERE query_json.id = i_json_id
AND rownum = 1;
EXCEPTION WHEN no_data_found THEN o_error := 'No Data Found';
WHEN others THEN o_error := sqlerrm;
END;
/
all call that from the current PRE-QUERY trigger.
can You explain me, where I did mistake in my code ?
CREATE OR REPLACE TRIGGER mda_01.tr_01_t01003 AFTER
INSERT ON mda_01.t01004_bo_semafor_log
FOR EACH ROW
DECLARE
PRAGMA autonomous_transaction;
BEGIN
IF inserting THEN
MERGE INTO mda_01.t01003_bo_semafor a
USING (
SELECT
:new.semafor_name,
:new.semafor_ts,
:new.semafor_status,
:new.semafor_desc
FROM
dual
) b
ON ( b.semafor_name = a.semafor_name )
WHEN MATCHED THEN UPDATE
SET a.semafor_ts = b.semafor_ts,
a.semafor_status = b.semafor_status
WHEN NOT MATCHED THEN
INSERT (
semafor_name,
semafor_ts,
semafor_status,
semafor_desc )
VALUES
( b.semafor_name,
b.semafor_ts,
b.semafor_status,
b.semafor_desc );
END IF;
COMMIT;
END;
/
I get an error:
LINE/COL ERROR
5/6 PL/SQL: SQL Statement ignored
16/8 PL/SQL: ORA-00904: "B"."SEMAFOR_NAME": invalid identifier
Errors: check compiler log
Thanks, Paul
I solved the problem.
I added aliases, and trigger was compiled with no errors:
SELECT
:new.semafor_name as semafor_name,
:new.semafor_ts as semafor_ts,
:new.semafor_status as semafor_status,
:new.semafor_desc as semafor_desc
FROM
dual
I have a table which have a field as nested table. I have a trigger on the first table, but it does not work and results on a :ORA-22903: MULTISET expression not allowed
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;
My trigger is:
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;
When I try something like that:
update t_taller set fec_fin = fec_fin + 20 where pk = 10;
I get the following error:
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'
Can you help me to solve this problem?
Thanks in advance.
Regards,
UPDATE
The trigger I posted is a dummy, but the error i get for the real one is the same, my real trigger is this
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;
Something else to say, I have a "AFTER INSERT" Trigger, and it Works fine:
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;
The procedure is:
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;
The insert Works fine:
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'
The line 451 of the package, is inside the procedure, exactly here:
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;
Sorry for not posted all the details from the begining, i wanted to summayrize and show just the error.
Regards
TABLE expression works if you are running a select query on the table itself.
Something like
SELECT T.DIA , T.HORA
FROM T_TALLER ,TABLE(:NEW.DIAS) T
But, you are not allowed to select from the Trigger owner as it leads to "table is mutating" error( ORA-04091 ).
You may instead loop through the nested table column using a simple 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;
/
By the way, as #XING mentioned, there's no use of dbms_output in a Trigger. You should rather consider logging them into a table.
Demo
As mentioned in my comments Triggers are used for handling of events on the table to . Although your posted script does not make much sense to me , however am giving the solution.
Also you simply cannot Select records from a Nested table. You need to use table operator to do so. Also in a trigger if you do Select on same table, you might land up is mutating, trigger/function. See below demo:
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;
Output:
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'
So again you need to revisit your requirement.
Table 1
ID
----------
1
2
3
4
5
Table 2
ID Desc
------------------------------
A1 Apple
A2 Pear
A3 Orange
I am trying to create a Function in Oracle, so that it add the prefix 'A' in Table 1, and after that I want to look up in Table 2 to get the DESC returned. It has to be a function.
Thank you!!!
You may use the following for creation of such a function :
Create or Replace Function Get_Fruit( i_id table2.description%type )
Return table2.description%type Is
o_desc table2.description%type;
Begin
for c in ( select description from table2 where id = 'A'||to_char(i_id) )
loop
o_desc := c.description;
end loop;
return o_desc;
End;
where
no need to include exception handling, because of using cursor
instead of select into clause.
using table_name.col_name%type for declaration of data types for
arguments or variables makes the related data type of the columns
dynamic. i.e. those would be able to depend on the data type of the
related columns.
the reserved keywords such as desc can not be used as column names
of tables, unless they're expressed in double quotes ("desc")
To call that function, the following might be preferred :
SQL> set serveroutput on
SQL> declare
2 i_id pls_integer := 1;
3 o_fruit varchar2(55);
4 begin
5 o_fruit := get_fruit( i_id );
6 dbms_output.put_line( o_fruit );
7 end;
8 /
Apple
PL/SQL procedure successfully completed
I am not sure with your question- Are you trying to achieve something like this:-
CREATE OR REPLACE FUNCTION Replace_Value
(
input_ID IN VARCHAR2
) RETURN VARCHAR2
AS
v_ID varchar(2);
BEGIN
begin
SELECT distinct a.ID into v_id from Table 2 a where a.ID in (select 'A'||b.id from table1 b where b.id=input_ID);
exception
when others then
dbms_output.put_line(sqlcode);
end;
RETURN v_id;
END Replace_Value;
Are you trying for something like this?
CREATE OR replace FUNCTION replace_value (table_name IN VARCHAR2,
input_id IN INTEGER)
RETURN VARCHAR2
AS
v_desc VARCHAR(20);
BEGIN
SELECT descr
INTO v_desc
FROM table2
WHERE id = 'A' || input_id
AND ROWNUM = 1; -- only needed if there are multiple rows for each id.
RETURN v_desc;
END replace_value;
You may also add an exception handling for NO_DATA_FOUND or INVALID_NUMBER
I got en error when attempting to use a BULK COLLECT statement ORA-00947: not enough values for table of objects.
Error occurs at the line from (select jta.nobject_id,
CREATE OR REPLACE TYPE "T_PPW_WORK" as object
(
nObjectKey number,
cJobType varchar2(500),
dPlanStart date,
dPlanEnd date,
cExecutor varchar2(500),
cComment varchar2(4000)
)
CREATE OR REPLACE TYPE "T_PPW_WORK_TABLE" as table of T_PPW_WORK;
function getPlannedOverdueJobs(in_nPlanKey number) return T_PPW_WORK_TABLE is
l_oWorks T_PPW_WORK_TABLE;
l_oWork T_PPW_WORK;
begin
select * bulk collect
into l_oWorks
from (select jta.nobject_id,
jt.cjobtype_name,
jta.dactual_start,
jta.dactual_finish,
st.familiya,
jta.ccomment
from ppw_jobtype_assign jta
left join pgts_sotrudnik st
on jta.nworkerid = st.npgts_sotrudnikkey
join ppw_jobtype jt
on jta.njobtype_id = jt.njobtype_key);
return l_oWorks;
end getPlannedOverdueJobs;
what is the reason?
select * bulk collect
into l_oWorks
from (select t_ppw_work(jta.nobject_id,
jt.cjobtype_name,
jta.dactual_start,
jta.dactual_finish,
st.familiya,
jta.ccomment)
from ppw_jobtype_assign jta
left join pgts_sotrudnik st
on jta.nworkerid = st.npgts_sotrudnikkey
join ppw_jobtype jt
on jta.njobtype_id = jt.njobtype_key);
You need to convert your result set using your defined object type (t_ppw_work) first.
You can do something like below instead.
CREATE OR REPLACE EDITIONABLE TYPE "F_OBJ" AS OBJECT (
Employee_name VARCHAR2(100),
Employee_id VARCHAR2 ( 100 ))
CREATE OR REPLACE EDITIONABLE TYPE "F_TAB" as table of F_OBJ
create or replace function "fname"
return f_tab
is
l_f_tab f_tab;
begin
SELECT f_obj(employee_name, employee_id) bulk collect into f_tab from employee_table;
return f_tab;
end;