Run sql code with variables in Oracle SQL Developer code window - oracle

I'm writing code using Oracle SQL Developer. I have a simple select statement that works:
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
CFS.LAST_USER_ID,
case
when 1 = 1 then
sl.usbank_to_edit
else
case
when 'ENT\CB174' = CFS.last_user_id then
sl.owner_to_edit
else
sl.to_edit
end
end canEdit
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
INNER JOIN caedbo.CAE_STATE_LOOKUP sl
ON (sl.object_state = CDSE_STAT.data_set_element_id)
where
cfs.CAE_SEC_ID in (3741, 3744, 3748, 3752);
However I want to add some variables to it and reference the variables in the statement, similar to below, and also run it in the code window. How do I do this correctly?
DECLARE
p_USBank_n NUMBER;
p_user_id_c VARCHAR2(20);
BEGIN
p_USBank_n := 1;
p_user_id_c := 'ENT\CB174';
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
CFS.LAST_USER_ID,
case
when p_USBank_n = 1 then
sl.usbank_to_edit
else
case
when p_user_id_c = CFS.last_user_id then
sl.owner_to_edit
else
sl.to_edit
end
end canEdit
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
INNER JOIN caedbo.CAE_STATE_LOOKUP sl
ON (sl.object_state = CDSE_STAT.data_set_element_id)
where
cfs.CAE_SEC_ID in (3741, 3744, 3748, 3752);
END;
When I run this in a sql window I get the message below:
Error report:
ORA-06550: line 8, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

if I am reading this correctly, I think you are looking for Oracle Substitution variables.
this will prompt you each time to input the values, by using &val it will prompt you # runtime
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
CFS.LAST_USER_ID,
CASE
when &p_USBank_n = 1 then
sl.usbank_to_edit
else
CASE
when '&p_user_id_c' = CFS.last_user_id then
sl.owner_to_edit
else
sl.to_edit
end
end canEdit
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
INNER JOIN caedbo.CAE_STATE_LOOKUP sl
ON (sl.object_state = CDSE_STAT.data_set_element_id)
where
CFS.CAE_SEC_ID IN (3741, 3744, 3748, 3752);
change it to &&var to have it retain the value, then use
UNDEFINE var
to clear it
Now you can set these at the top of the page (thus avoiding the prompt) by utilizing DEFINE as such
DEFINE XYZ = 5
DEFINE AAA = to_date('10/10/2010','mm/dd/rrrr')
DEFINE textString = AaBbCc
SELECT &&XYZ b, &&AAA a, '&&textString' textString
from dual ;
B A TEXTSTRING
---------------------- ------------------------- ----------
5 10.OCT.2010 00:00 AaBbCc
--typing define will show you all the "defined" values
define
DEFINE XYZ = "5"
DEFINE TEXTSTRING = "AaBbCc"
DEFINE AAA = "to_date('10/10/2010','mm/dd/rrrr')"
the double ampersand will 'retain' the value until you UNDEFINE it (see above) or redefine it.

The error message explains the problem; inside a PL/SQL block you have to select INTO something, and you can't just dump the results of a query to screen as you can with plain SQL. (There are ways to do it but probably overly complicated for what it looks like you're trying to achieve here).
If you don't want to use substitution variables as #Harrison suggested, you can use bind variables which you define at the start in a separate anonymous block. You can then refer to the bind variable in the plain SQL:
var p_usbank_n number;
var p_user_id_c varchar2(20);
exec :p_usbank_n := 1;
exec :p_user_id_c := 'ENT\CB174';
select
cfs.cae_sec_id,
cfs.fm_sec_code,
cfs.last_user_id,
case
when 1 = :p_usbank_n then
sl.usbank_to_edit
when cfs.last_user_id = :p_user_id_c then
sl.owner_to_edit
else
sl.to_edit
end as canEdit
from
caedbo.cae_fof_security cfs
inner join caedbo.cae_data_set_element cdse_stat
on (cdse_stat.data_set_element_id = cfs.appr_status)
inner join caedbo.cae_state_lookup sl
on (sl.object_state = cdse_stat.data_set_element_id)
where
cfs.cae_sec_id in (3741, 3744, 3748, 3752);

Related

Write an Oracle procedure

I must create an oracle procedure to display a list of persons (parlimentaries) with an index for tuples.
For now, I wrote this piece of code (I haven't implemented the index)
create or replace procedure parlamentarieslist as
begin
select
ssn,
name,
surname,
from
parlimentaries p,
mandate m
where
p.ssn = m.parlamentaries AND m.legislature= (select
max(legislature) "m"
from mandate);
end parlamentarieslist;
However, oracle give me these errors
Error(5,3): PL/SQL: SQL Statement ignored
Error(12,3): PL/SQL: ORA-00936: missing expression
Why?
As I mentioned before in the comment part, the problem is due to
the missing INTO clause
existing typo(comma) after surname column in the uppermost select list.
Mostly, Procedures are used to return one column or single row and in results of SELECT statements may be returned to the output parameters by INTO clause. But, If you want to return list of persons (multi-rows), the following style may be more suitable :
SQL> set serveroutput on;
SQL> create or replace procedure parlamentarieslist as
begin
for c in
(
select p.ssn, p.name, p.surname,
max(m.legislature) over (partition by p.ssn ) m
from parlimentaries p inner join mandate m
on ( p.ssn = m.parlamentaries )
order by m.legislature desc
)
loop
dbms_output.put_line(' SSN : '||c.ssn||' Name : '||c.name||' Surname : '||c.surname);
end loop;
end parlamentarieslist;
/
SQL> exec parlamentarieslist;
Where Use a SQL of explict ANSI JOIN style, instead of old-fashioned comma seperated JOIN style.

Oracle SQL Compiles, but seems to break out of loop when select loop returns nothing/empty

I am still quite new to pl/sql... but here I have a script that works well when data exists...But I also need it to work when the select statement does NOT have any value to return (is empty). When the select statement is empty, dbms_output.put_line does not show anything, even when I write a complete string there, so I think the loop is exiting when nothing is found. Online, I stumbled upon Union and Exception...but nothing that seems to work accurately in a loop.
WHAT I AM ASKING IS: How to run this script even when data DOES NOT EXIST??? AND How do I tell which value is empty? Is it the postal_code or the fipcode, or BOTH?
DECLARE
F33_35 VARCHAR2(3) := rpad('0',3,'0');
BEGIN
FOR tabVals IN (SELECT DISTINCT pa.postal_code, fip.fipcode
FROM voucher v
INNER JOIN cc_authorization cca
ON cca.cc_authorization_id = v.cc_authorization_id
INNER JOIN episode e
ON cca.subsidy_id = e.episode_id
INNER JOIN case c
ON c.case_id = e.case_id
INNER JOIN invoice_item ii
ON ii.voucher_id = v.voucher_id
INNER JOIN invoice i
ON i.invoice_id = ii.invoice_id
INNER JOIN svcperiod_info s
ON s.svcperiod_id = i.svcperiod_id
INNER JOIN party_contact_mech pcm
ON pcm.party_id = c.identifying_party
INNER JOIN postal_address pa
ON pcm.contact_mech_id = pa.contact_mech_id
INNER JOIN VT_FIPS_MAP fip
ON substr(pa.POSTAL_CODE,1,5) = substr(fip.ZIPCODE,1,5)
WHERE ii.status = 8 AND
ii.net_amount > 0 AND
s.end_dt >= DATE'2017-04-01' AND
s.end_dt < DATE'2017-04-30' AND
c.case_id = 104570 AND
pcm.contact_mech_purpose_cd = 4 AND
pcm.current_ind = 1
ORDER BY POSTAL_CODE, FIPCODE)
LOOP
F33_35 := substr(F33_35 || tabVals.fipcode,-3);
DBMS_OUTPUT.PUT_LINE('F String: 50' || F33_35);
--- RESET certain variables for loop
F33_35 := rpad('0',3,'0');
END LOOP;
END;
you are correct when you say
...I think the loop is exiting when nothing is found...
the cursor for loop can be considered a special case of regular loop.
eg.
for a in (<select statement>) LOOP
--do stuff here
END LOOP;
is effectively just shorthand for
declare
cursor c is
<select statement>;
a c%ROWTYPE;
begin
open c;
LOOP
FETCH c INTO a;
EXIT WHEN c%NOTFOUND;
--do stuff here
END LOOP;
so you can no see that no code would be executed if the query returns 0 rows.
possible the best solution for running code if your statement returns 0 rows is to set a flag inside the loop and check it afterwards. (as suggested by #tony-Andrews )
a second option is to rewrite as the long version of the loop above and move the EXIT WHEN statement to after the "do stuff"

PLSQL Loop taking lot of time to execute

I have a Oracle procedure which is updating below 10,000 records. if I run the normal SQL statement, it is returning the result immediately with in seconds(30).
same statment in procedure loop it is going to endlessly.
My loop statment below.
Note: data FIELD Data type is a clob not varchar2.
statment:
select
'LB_COPY_CHANGE-'||8 LAST_MODIFIED_BY,
rec.COR_ID_old,
rec.COR_ID_NEW,
replace(replace(replace(a.data,'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||','),''id':'||rec.COR_ID_OLD||',',''id':'||rec.COR_ID_NEW||','),'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||',') as data
from KPI_MET_FIELD_DATA a, CUSTOM_TEMP_TABLE_SESSION_1 rec
where A.cmf_fk_id in (145,146,147)
and TYPE_LB in (14,15,16)
and a.KDB_FK_ID in (
select distinct km.KDB_FK_ID
from KPI_MET_FIELD_DATA km , KPI_DET_BASE kp, KPI_REL_KPI_SCORECARD ksc, STR_DET_EMP_SCORECARD sc
where ksc.SDE_FK_ID=sc.SDE_PK_ID
and km.KDB_FK_ID = ksc.KDB_KPI_FK_ID
and km.is_deleted=0
and kp.kdb_pk_id = km.KDB_FK_ID
and kp.is_deleted=0
and km.cmf_fk_id in (145,146,147)
and sc.sdp_fk_id = 8)
and a.is_deleted=0
and (a.data like '%'||rec.COR_ID_OLD||'%');
FOR rec in (SELECT * FROM CUSTOM_TEMP_TABLE_SESSION where TYPE_LB in (14,15,16)) LOOP
update KPI_MET_FIELD_DATA
set LAST_MODIFIED_BY='LB_COPY_CHANGE-'||p2 ,
data = replace(replace(replace(data,'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||','),''id':'||rec.COR_ID_OLD||',',''id':'||rec.COR_ID_NEW||','),'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||',')
where cmf_fk_id in (145,146,147)
and KDB_FK_ID in (
select distinct km.KDB_FK_ID
from KPI_MET_FIELD_DATA km , KPI_DET_BASE kp, KPI_REL_KPI_SCORECARD ksc, STR_DET_EMP_SCORECARD sc
where ksc.SDE_FK_ID=sc.SDE_PK_ID
and km.KDB_FK_ID = ksc.KDB_KPI_FK_ID
and km.is_deleted=0
and kp.kdb_pk_id = km.KDB_FK_ID
and kp.is_deleted=0
and km.cmf_fk_id in (145,146,147)
and sc.sdp_fk_id = p2)
and is_deleted=0 ;
There are several weaknesses in your code.
WHERE KDB_FK_ID in (select distinct ... does not make any sense. There is no need to make DISTINCT for an IN () clause.
Use ANSI join syntax instead of old Oracle join syntax, it is less error-prone
But the main difference is, your loop does not contain join condition (a.data like '%'||rec.COR_ID_OLD||'%'), i.e. you update entire table KPI_MET_FIELD_DATA again and again for each row in CUSTOM_TEMP_TABLE_SESSION where TYPE_LB in (14,15,16)

Oracle Merge statement error in procedure package body

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)

ORA-00905: missing keyword error oracle

Hi when i am trying to execute following oracle query I am getting
[Err] ORA-00905: missing keyword
CREATE VIEW MJNSXJJRW_view AS
SELECT B.oID AS "_oid", B.oTm AS "_otm"
FROM
(SELECT DISTINCT oID, oTm FROM MJNSXJJRW) B
LEFT JOIN MJNSXJJRW AS S0 ON
B.oID = S0.oID AND
S0.idx = 0 AND
S0.kID = "str_val" ;
The most likely issue is MJNSXJJRW AS S0. You use the AS keyword when defining column aliases, not when defining table aliases.
CREATE VIEW MJNSXJJRW_view AS
SELECT B.oID AS "_oid", B.oTm AS "_otm"
FROM
(SELECT DISTINCT oID, oTm FROM MJNSXJJRW) B
LEFT JOIN MJNSXJJRW S0 ON
B.oID = S0.oID AND
S0.idx = 0 AND
S0.kID = "str_val" ;
I'm assuming that "str_val" is a column, not a string literal. If it's the latter you should use single quotes.

Resources