Oracle Merge statement error in procedure package body - oracle

I'm struggling trying to make this procedure to work, I have the following code inside my package body:
PACKAGE BODY PKG_DM_TRANS_DIMENSIONES AS
PROCEDURE SP_DM_TRANS_DIM_CUENTA AS
vNumRegistrosDimCuentas NUMBER;
BEGIN
SELECT COUNT(*) INTO vNumRegistrosDimCuentas
FROM DIM_CUENTAS;
IF (vNumRegistrosDimCuentas <> 0) THEN
MERGE INTO DIM_CUENTAS DIMC
USING (
SELECT * FROM (
SELECT
DIM.FNT_CUENTA_ID AS DIM_CUENTA_ID,
C.CUE_ID AS FNT_CUENTA_ID,
R.REG_REGION AS REGION,
P.PAI_PAIS AS PAIS,
E.EDI_NOMBRE_EDIFICIO AS EDIFICIO,
C.CUE_CUENTA,
TIC.TIC_TIPO_CONTACTO,
C.CUE_STATUS,
CASE
WHEN DIM.FNT_CUENTA_ID IS NULL THEN 1
WHEN
R.REG_REGION <> DIM.REGION OR
P.PAI_PAIS <> DIM.PAIS OR
E.EDI_NOMBRE_EDIFICIO <> DIM.EDIFICIO OR
C.CUE_CUENTA <> DIM.CUENTA OR
TIC.TIC_TIPO_CONTACTO <> DIM.TIPO_CONTACTO
THEN 2
ELSE 0
END AS TIPO_FILA
FROM STA_EDIFICIOS_EXTRACCION E
LEFT JOIN
STA_PAISES_EXTRACCION P ON E.EDI_PAI_ID = P.PAI_ID
LEFT JOIN
STA_REGIONES_EXTRACCION R ON P.PAI_REG_ID = R.REG_ID
LEFT JOIN
EUB_EDIFICIO_UBICACION EUB ON EUB.EUB_EDI_ID = E.EDI_ID
LEFT JOIN
STA_CUENTAS_EXTRACCION C ON C.CUE_EUB_ID = EUB.EUB_ID
LEFT JOIN
STA_TIPOS_CONTACTO_EXTRACCION TIC ON TIC.TIC_ID = C.CUE_TIC_ID
LEFT JOIN
DIM_CUENTAS DIM ON
(C.CUE_ID = DIM.FNT_CUENTA_ID AND DIM.CUENTA_STATUS = 1)
)
) Q
ON (DIMC.FNT_CUENTA_ID = Q.TIPO_FILA)
WHEN MATCHED THEN
INSERT (DIMC.REGION, DIMC.PAIS, DIMC.EDIFICIO, DIMC.CUENTA, DIMC.TIPO_CONTACTO, DIMC.CUENTA_FECHA_CREACION, DIMC.FNT_CUENTA_ID)
VALUES (Q.REGION, Q.PAIS, Q.EDIFICIO, Q.CUE_CUENTA, Q.TIC_TIPO_CONTACTO, TO_TIMESTAMP(sysdate, 'MM/DD/YYYY HH24:MI:SS'), Q.FNT_CUENTA_ID)
WHEN NOT MATCHED THEN
UPDATE SET DIMC.CUENTA_STATUS = 0 WHERE DIMC.CUENTA_STATUS = 1 -- <- dummy update stmt
ELSE ..... -- else statement code working fine...
END IF;
END SP_DM_TRANS_DIM_CUENTA;
END PKG_DM_TRANS_DIMENSIONES;
I'm getting erros at the line
MERGE INTO DIM_CUENTAS DIMC
Saying "Statement ignored"
and then, another error at:
INSERT (DIMC.REGION, DIMC.PAIS, DIMC.EDIFICIO, DIMC.CUENTA, DIMC.TIPO_CONTACTO, DIMC.CUENTA_FECHA_CREACION, DIMC.FNT_CUENTA_ID)
VALUES (Q.REGION, Q.PAIS, Q.EDIFICIO, Q.CUE_CUENTA, Q.TIC_TIPO_CONTACTO, TO_TIMESTAMP(sysdate, 'MM/DD/YYYY HH24:MI:SS'), Q.FNT_CUENTA_ID)
saying "missing keyword". Is it possible to use the merge statement in a SP? I'm new to Oracle so I really don't know if what I'm trying to do is possible or if there's something wrong with my code.
Thanks for any help, I would really appreaciate it.

I think that you swapped commands - after when matched you should put update statement and after not matched - insert.
Similar example worked for me, but after swapping statements I got ORA-00905 missing keyword. So correct version is:
merge into t1
using (select * from t2) t2 on (t1.id = t2.id)
when matched then update set t1.name = t2.name
when not matched then insert (id, name) values (t2.id, t2.name)

Related

How to update and set values based on multiple joins in select statment?

I want to update a column prtnum and revlvl in table invdtl based on value from select statment, here is the code
update invdtl set invdtl.prtnum = usr_prtmst_xref.prtnum,invdtl.revlvl =
usr_prtmst_xref.colnam ([select
invdtl.prtnum,usr_prtmst_xref.prtnum AS
crossref,invdtl.revlvl,aremst.arecod,aremst.fwiflg from invdtl
join usr_prtmst_xref
on usr_prtmst_xref.prtnum = usr_prtmst_xref.prtnum
join invsub
join invlod
join locmst
join aremst
on aremst.arecod = locmst.arecod
and aremst.wh_id = locmst.wh_id
on locmst.stoloc = invlod.stoloc
and locmst.wh_id = invlod.wh_id
on invlod.lodnum = invsub.lodnum
on invsub.subnum = invdtl.subnum where aremst.arecod = 'EXPR' or
aremst.fwiflg = '1' and rownum <2])
I want to copy two values prtnum and revlvl that are returned by select statement but there is some syntax issue.
There are a bunch of errors here:
The syntax for a multi-column update is basically
update blah
set ( col1, col2 ) = ( select x, y
from
...
)
The syntax for multiple joins is basically
from table1 t1
join table2 t2
on t1.col = t2.col
join table3 t2 on
t2.col = ...
Get ride of "[" and "]"
The predicate rownum<2 is probably to get around the message you received, something like "single row sub-query returns more than 1
row" Which this predicate "fixes" that problem, you are just getting
the first random row; probably not what you want. You probably need to
correlate the sub-query with the update
I would fix these basic syntax errors and try again.

ORACLE ERROR missing right parenthesis

I have a problem, I don't understand why do I have this error..
The problem is in the creation of the cursor, but i don't understand why he says that missing a right parentesis...
This is my code :
CREATE OR REPLACE FUNCTION classementEtudiantSemestre( p_idEtudiant IN Etudiants.idEtudiant%TYPE, p_idSemestre IN Semestres.idSemestre%TYPE) RETURN NUMBER IS
CURSOR cur_lesmoys IS (
SELECT DISTINCT moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre)
FROM ETUDIANTS E
JOIN GROUPES G ON G.idGroupe=E.idGroupe
JOIN SEMESTRES S ON G.idPromotion = S.idPromotion
WHERE idSemestre=p_idSemestre
ORDER BY moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre) DESC
);
u_classement NUMBER:=1;
BEGIN
FOR rty_lesmoys IN cur_lesmoys LOOP
IF rty_lesmoyes.moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre)=moyenneEtudiantSemestreAvecAbs(p_idEtudiant, p_idSemestre) THEN
RETURN u_classement;
ELSE
u_classement := u_classement +1;
END IF;
END LOOP;
END;
ORACLE ERRORS :
3/23 PL/SQL: SQL Statement ignored
9/31 PL/SQL: ORA-00907: missing right parenthesis
Help me please..
Does this work (i.e. with no brackets and naming the calculated column)?
CURSOR cur_lesmoys IS
SELECT DISTINCT moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre) AS resultCol
FROM ETUDIANTS E
JOIN GROUPES G ON G.idGroupe=E.idGroupe
JOIN SEMESTRES S ON G.idPromotion = S.idPromotion
WHERE idSemestre=p_idSemestre
ORDER BY moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre) DESC
;
If it's still not working, make sure this query works, you might have mistyped the name of a table/column
SELECT DISTINCT moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre)
FROM ETUDIANTS E
JOIN GROUPES G ON G.idGroupe=E.idGroupe
JOIN SEMESTRES S ON G.idPromotion = S.idPromotion
WHERE idSemestre=p_idSemestre
ORDER BY moyenneEtudiantSemestreAvecAbs(idEtudiant, idSemestre) DESC
It's better to focus on the first error, the second one can often be caused by the first and be confusing.

Why sub SQL in FROM area can't be null?

select col_1,
col_2
from tbl_a A,
tbl_b B,
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
where A.col_1 = B.col_1
and A.col_2 = B.col_2
and (A.col_2 = B.col_2
or C.col_2 = A.col_2);
My environment is Oracle,when I run this SQL,if the sub SQL C hasn't got a result,then the entire SQL returns NULL.Whereas if C has a result(not null) which fits other condions,there could be a result.Would somebody explain why sub SQL at the from area need to be not NULL?Thanks very much.
You need to bring yourself into the 90s and start using standard joins:
select col_1,
col_2
from tbl_a A
inner join
tbl_b B
on A.col_1 = B.col_1
and A.col_2 = B.col_2
left join
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
on
C.col_2 = A.col_2
As a guess. I'm not entirely sure what your join conditions should be but that's my first attempt.
This is expected behaviour. When you join two result sets, you only want to get results where the join criteria is satisfied. If the criteria are not satisfied, you should get no results.
If I run the query "get me all the employees older than 65, and get their departments", if there are no employees older than 65, you would not expect to get any results, even if there are some departments in the database.
SELECT emp.name, dept.dept_name
FROM emp
JOIN dept
ON (emp.dept_no = dept.dept_no)
WHERE emp.age > 65;
As the others said, if you actually want to get rows regardless of whether the subquery has any results, you need to use an outer join.

Copy data from a column in some rows to another column in other rows in oracle

quite the same question as here : Copy data from one existing row to another existing row in SQL?
but in Oracle, where update ... from and update t1, t2 are not supported.
I'll repeat it here in my own words ;
I have a table T, which looks like this :
and as the arrow shows it, I want to copy everything from r where c = 1 to e where c = 2, with t matching.
I have the select statement to get what I want to copy :
select
told.t,
told.r
from
T told
inner join
T tnew
on
told.t= tnew.t
where
told.c = 1
and
tnew.c = 2
I just don't know how to put this together in an update. An Oracle update, specifically.
try this:
update T tnew
set tnew.e = (select told.r from T told where told.c = 2 and told.t = tnew.t)
where tnew.c = 1
Sounds like the time for a bulk collects! Not as pretty as AB Cade's solution but more efficient.
declare
c_data is
select t1.rowid as rid, t2.r
from my_table t1
join my_table t2
on t1.t = t2.t
where t1.c = 2
and t2.c = 1
;
type t__data is table of c_data index by binary_integer;
t_data t__data;
begin
open c_data;
loop
fetch c_data bulk collect into t_data limit 25000;
exit when t_data.count = 0;
forall i in t_data.first .. t_data.last loop
update my_table
set e = t_data(i).r
where rowid = t_data(i).rid
;
commit;
end loop;
close c_data;
end;
/

Need a fix for merge update query (Simple but still confusing)

MERGE INTO table_1 a
USING
(SELECT * from table_2) b ON ( a.row_id = b.row_id and a.in_correct IS NULL)
WHEN MATCHED THEN UPDATE SET a.in_correct = 'Y';
In the above query ORA-38104:Column referenced in ON clause cannot be updated.
I have been sitting for hours to resolve this.
I have identified that the problem is the field in_correct.
This field "in_correct" cannot be put in both ON clause and also after SET. But in order satisfy my criteria,I have no option.
Please help me out
MERGE INTO table_1 a USING
(SELECT * from table_2) b
ON ( a.row_id = b.row_id)
WHEN MATCHED THEN UPDATE
SET a.in_correct = NVL(in_correct, 'Y');
UPDATE:
A more "general" command (for non null values):
MERGE INTO table_1 a USING
(SELECT * from table_2) b
ON ( a.row_id = b.row_id)
WHEN MATCHED THEN UPDATE
SET a.in_correct = case
when in_correct = 'valuetobereplaced' then 'Y';
else in_correct;
end;

Resources