How to trace abnormal termination in pl sql - oracle

I have a pl sql file which process around 7000 records. Based on input it does select insert ,update to different table. Exception handler is written in each query. But my program terminates abnormally without displaying any error message. And this termination happens at different places of code at each time. First time it may process 1200 records, next time it process 1400. Is it related to cache issue? Please provide the input to resolve this issue. I am using sql developer 1.5.4. Is there any way to debug such scenario?
Adding Pl sql file:
Below is my pl sql file and which reads the input from 'marx_resph_bk.txt' as mentioned in file.
=================================================================================
SET SERVEROUTPUT ON;
exec dbms_output.enable(NULL);
declare
v_line varchar2(500);
v_cnt integer;
v_cntp integer:=0;
v_cnth integer:=0;
v_file_date date := to_date('20140201','yyyymmdd');
v_avail_date date := to_date('20131210','yyyymmdd');
v_sent_date date;
v_eff_date date;
v_status char;
ACCEPTED char := 'A';
REJECTED char := 'R';
v_tracking_id kc.kc_marx_transaction.kmt_marx_tsa_sk%type;
v_hicn kc.kc_marx_transaction.kmt_hicn_id%type;
v_c_id kc.kc_marx_transaction.c_id%type;
v_trcs kc.kc_marx_transaction.kmt_tsa_rpy_cd%type;
v_disp_cd kc.kc_marx_transaction.kmt_disp_cd%type;
v_pl_id kc.kc_hcfa_mbr_transaction.pl_id%type;
v_cms_ttc kc.kc_hcfa_mbr_transaction.kcmt_type_code%type;
v_ic_ttc kc.kc_hcfa_mbr_transaction.kcmt_type_code%type;
v_td_id kc.kc_validations.td_id%type;
v_qd_id kc.kc_validations.qd_id%type;
f_verbatim utl_file.file_type;
f_errors utl_file.file_type;
cursor c_Trcs is
select kcmt_reply_code trc
from kc.kc_hcfa_mbr_transaction
where c_id = v_c_id
and pl_id = v_pl_id
and kcmt_file_date = v_file_date
and kcmt_cms_aval_dt = v_avail_date
and kcmt_type_code = v_cms_ttc;
begin
utl_file.fclose(f_verbatim);
utl_file.fclose(f_errors);
f_verbatim := utl_file.fopen ('/net/iRX_downloads2/work/infocare_utl', 'marx_resph_bk.txt', 'r');
f_errors := utl_file.fopen('/net/iRX_downloads2/work/infocare_utl', 'marx_result.txt', 'w');
<<next_hic>>
loop
begin
utl_file.get_line(f_verbatim, v_line);
v_cntp := v_cntp+1;
dbms_output.put_line(' Line CNT: '||v_cntp);
exception
when no_data_found then
dbms_output.put_line(' No Line');
exit;
end;
v_hicn := substr(v_line,1,10);
v_status := substr(v_line,474,1);
v_tracking_id := to_number(substr(v_line,486,15));
begin
dbms_output.put_line(' Selecting marx_transaction');
select c_id, substr(kmt_ctc_id,2,4), kmt_tsa_cd, kmt_eff_dt,
kmt_snt_to_marx_sys_dt, nvl(kmt_disp_cd,'X')
into v_c_id, v_pl_id, v_ic_ttc, v_eff_date, v_sent_date, v_disp_cd
from kc.kc_marx_transaction
where kmt_marx_tsa_sk = v_tracking_id;
if v_disp_cd <> 'X' then
dbms_output.put_line(' Skipping');
goto next_hic;
end if;
exception
when others then
dbms_output.put_line(' Selecting tracking Id');
utl_file.putf(f_errors, 'Select Tracking ID :'||v_tracking_id
||':'||sqlerrm);
rollback;
return;
end;
if v_pl_id = '3909' then
v_pl_id := '3963';
end if;
v_cms_ttc := v_ic_ttc;
v_td_id := null;
v_qd_id := null;
case
when v_ic_ttc = '51' then
v_td_id := '50'; v_qd_id := '85';
when v_ic_ttc = '61' then
v_td_id := '10'; v_qd_id := '20';
when v_ic_ttc = '71' then
v_td_id := '90'; v_qd_id := '140'; v_cms_ttc := '61';
when v_ic_ttc = '73' then
v_td_id := '73'; v_qd_id := '445';
when v_ic_ttc = '75' then
v_td_id := '72'; v_qd_id := '430';
when v_ic_ttc in ('72','76','78','80','81') then
null;
else
utl_file.putf(f_errors, 'Invalid TTC:'||v_ic_ttc||':Tracking ID :'
||v_tracking_id);
dbms_output.put_line(' Invalid TTC:');
goto next_hic;
end case;
if v_status = REJECTED then
begin
delete kc.kc_validations
where c_id = v_c_id
and pl_id = v_pl_id
and td_id = v_td_id
and ec_code like 'C%';
exception
when others then
null;
end;
end if;
v_cnt := 0;
v_trcs := null;
for l_1 in c_Trcs loop
v_trcs := v_trcs||l_1.trc;
v_cnt := v_cnt + 1;
dbms_output.put_line(' Inside Cursor loop');
-- Only need to store validation errors for those TTCs that can be
-- worked through the browse queue screens in the front end
if v_status = REJECTED and v_td_id is not null then
begin
insert into kc.kc_validations
(c_id, pl_id, td_id, qd_id, ec_code, v_column_db_name, v_update_date)
values
(v_c_id, v_pl_id, v_td_id, v_qd_id, 'C'||l_1.trc, ' ', sysdate);
exception
when others then
dbms_output.put_line(' Validation Insert:');
utl_file.putf(f_errors, 'Validation Insert: c_id :'||v_c_id
||': pl_id :'||v_pl_Id||': td_id :'||v_td_id||': '||sqlerrm);
rollback;
return;
end;
if (l_1.trc = '127' or l_1.trc = '169') and v_ic_ttc = '61' then
begin
update kc.kc_customer_coverages_new
set ccv_prj_eff_date = v_eff_date,
ccv_accrete_eff_date = v_sent_date,
ccv_ssa_medd_wth_prem_eff_dt = v_eff_date,
ccv_lis_eff_dt = v_eff_date,
ccv_update_date = sysdate,
ccv_update_userid = user,
cet_type = '4A'
where c_id = v_c_id
and pl_id = v_pl_id;
exception
when others then
dbms_output.put_line(' Error found CCV');
utl_file.putf(f_errors, 'CCV Update:c_id:'||v_c_id||':pl_id:'
||v_pl_id||':eff_dt:'||to_char(v_eff_date,'yyyymmdd')||':'
||'sent_dt:'||to_char(v_sent_date,'yyyymmdd')||':'||sqlerrm);
rollback;
return;
end;
end if;
end if;
-- KC.KC_MARX_TRANSACTION.KMT_TSA_RPY_CD is only large enough to
-- accommodate a string of five TRCs (rarely, if ever, is this needed)
if v_cnt = 5 then
exit;
end if;
end loop;
begin
v_cnth := v_cnth+1;
dbms_output.put_line(' CNT: '||v_cnth);
dbms_output.put_line('v_status: '||v_status||' v_trcs: '||v_trcs||' v_tracking_id: '||v_tracking_id );
dbms_output.put_line(' v_C_ID: '||v_c_id||' v_hicn: '||v_hicn);
update kc.kc_marx_transaction
set kmt_disp_cd = v_status,
kmt_tsa_rpy_cd = v_trcs,
kmt_rsp_pcs_by_marx_sys_dt = sysdate,
last_upd_use_id = user,
last_upd_ts = sysdate,
last_upd_pgm_nm = 'ACCRETION II - ACCR_ACC_REJ_STATUS.SQL'
where kmt_marx_tsa_sk = v_tracking_id;
exception
when others then
dbms_output.put_line(' Error Update Tracking');
utl_file.putf(f_errors, 'Update Tracking ID :'||v_tracking_id
||':'||sqlerrm);
rollback;
return;
end;
end loop;
dbms_output.put_line('TOTAL CNT: '||v_cnth);
utl_file.fclose(f_verbatim);
utl_file.fclose(f_errors);
commit;
end;
/
==============================================================================
And it never reach to a point whereit can display my final dbms_output.put_line for Total CNT.

You exception handler
when others then
dbms_output.put_line(' Selecting tracking Id');
utl_file.putf(f_errors, 'Select Tracking ID :'||v_tracking_id
||':'||sqlerrm);
rollback;
return;
contains error tracking write to file - what about dbms_output.put_line() with the same information ? You could get this as spool file output. Also seems you use loop - end loop; and goto control method - could you use while() looping instead ? It might be more transaparent.
Ald also you have a problem with RETURN statement I guess - because you don't close file handler before return in nested block you don't have information about the error, the file is empty and you don't reach the end of main block:
SQL> declare
2
3 f_errors utl_file.file_type;
4
5 begin
6 utl_file.fclose(f_errors);
7 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
8 begin
9
10 raise no_data_found;
11
12 exception
13 when others then
14 dbms_output.put_line(' Selecting tracking Id');
15 utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
16 rollback;
17 return;
18 end;
19 utl_file.fclose(f_errors);
20 end;
21 /
Selecting tracking Id
SQL> declare
2
3 f_errors utl_file.file_type;
4 buff varchar2(4000);
5
6 begin
7 utl_file.fclose(f_errors);
8 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
9 utl_file.get_line(f_errors, buff, 4000);
10 dbms_output.put_line(buff);
11 utl_file.fclose(f_errors);
12 end;
13 /
declare
*
error in line 1:
ORA-01403: data not found
ORA-06512: at "SYS.UTL_FILE", line 106
ORA-06512: at "SYS.UTL_FILE", line 746
ORA-06512: at line 9
SQL> declare
2
3 f_errors utl_file.file_type;
4
5 begin
6 utl_file.fclose(f_errors);
7 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
8 begin
9
10 raise too_many_rows;
11
12 exception
13 when others then
14 dbms_output.put_line(' Selecting tracking Id');
15 utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
16 utl_file.fclose(f_errors);
17 rollback;
18 return;
19 end;
20 utl_file.fclose(f_errors);
21 end;
22 /
Selecting tracking Id
SQL> declare
2
3 f_errors utl_file.file_type;
4 buff varchar2(4000);
5
6 begin
7 utl_file.fclose(f_errors);
8 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
9 utl_file.get_line(f_errors, buff, 4000);
10 dbms_output.put_line(buff);
11 utl_file.fclose(f_errors);
12 end;
13 /
Select Tracking ID :ORA-01422: exact fetch returns more than requested number of rows
SQL> declare
2
3 f_errors utl_file.file_type;
4
5 begin
6 utl_file.fclose(f_errors);
7 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
8 begin
9
10 raise invalid_number;
11
12 exception
13 when others then
14 dbms_output.put_line(' Selecting tracking Id');
15 utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
16 rollback;
17 end;
18 utl_file.fclose(f_errors);
19 end;
20 /
Selecting tracking Id
SQL> declare
2
3 f_errors utl_file.file_type;
4 buff varchar2(4000);
5
6 begin
7 utl_file.fclose(f_errors);
8 f_errors := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
9 utl_file.get_line(f_errors, buff, 4000);
10 dbms_output.put_line(buff);
11 utl_file.fclose(f_errors);
12 end;
13 /
Select Tracking ID :ORA-01722: invalid_number

Related

How to create dynamic cursor in PLSQL - Oracle

I cannot create this cursor dynamically, I only have to modify the name of the table in the statement. But it returns me error.
What am I doing wrong or what am I missing to create the dynamic cursor?
The dynamic statement is in the Lv_SQL variable and I call the cursor C_DATOS but it does not recognize it.
PROCEDURE PROC_CAB_DET(Pv_corte VARCHAR2, Pv_MsjError IN OUT VARCHAR2) IS
Lv_Table VARCHAR2(100);
Lv_SQL VARCHAR2(5000);
C_DATOS SYS_REFCURSOR;
BEGIN
Lv_Table := NULL;
IF (Pv_corte IN ('02', '03')) THEN
Lv_Table := 'TABLE_TMP_MOV';
ELSIF (Pv_corte IN ('14', '15')) THEN
Lv_Table := 'TABLE_TMP_FIX';
ELSE
Lv_Table := 'TABLE_TMP_CMF';
END IF;
Lv_SQL := 'SELECT cuenta, campo_2 RUBRO
FROM ' || Lv_Table || '
WHERE codigo = 1
AND CAMPO_3 != "000"
AND (campo_2 NOT IN (SELECT RUBRO FROM GSI_QC_RUBROS_CABECERA)
AND upper(campo_2) NOT LIKE "NAN%")
MINUS
SELECT cuenta, campo_2 RUBRO
FROM ' || Lv_Table || '
WHERE codigo=4
AND campo_2 != "ICE (12%)"';
OPEN C_DATOS FOR Lv_SQL;
FOR I IN C_DATOS LOOP
INSERT INTO GSI_QC_CBS_CASOS_ERROR(CUENTA, ID_ESCENARIO, DATO_TMP_1)
VALUES(I.CUENTA, 'IdEscenario', 'DATA');
END LOOP;
COMMIT;
CLOSE C_DATOS;
EXCEPTION
WHEN OTHERS THEN
Pv_MsjError := SQLERRM;
END PROC_CAB_DET;
PLS-00221: C_DATOS is not a procedure or is undefined
You can't enclose strings into double quotes; have to be single ones. To make it simpler, use the q-quoting mechanism. Also, you wrongly looped through refcursor.
I created dummy tables to make that procedure compile; I don't know whether code does what you planned.
SQL> create or replace
2 PROCEDURE PROC_CAB_DET(Pv_corte VARCHAR2, Pv_MsjError IN OUT VARCHAR2) IS
3 Lv_Table VARCHAR2(100);
4 Lv_SQL VARCHAR2(5000);
5 C_DATOS SYS_REFCURSOR;
6 --
7 l_cuenta table_tmp_mov.cuenta%type;
8 l_rubro table_tmp_mov.campo_2%type;
9 BEGIN
10 Lv_Table := NULL;
11 IF (Pv_corte IN ('02', '03')) THEN
12 Lv_Table := 'TABLE_TMP_MOV';
13 ELSIF (Pv_corte IN ('14', '15')) THEN
14 Lv_Table := 'TABLE_TMP_FIX';
15 ELSE
16 Lv_Table := 'TABLE_TMP_CMF';
17 END IF;
18
19 Lv_SQL := 'SELECT cuenta, campo_2 RUBRO
20 FROM ' || Lv_Table || q'[
21 WHERE codigo = 1
22 AND CAMPO_3 != '000'
23 AND (campo_2 NOT IN (SELECT RUBRO FROM GSI_QC_RUBROS_CABECERA)
24 AND upper(campo_2) NOT LIKE 'NAN%')
25 MINUS
26 SELECT cuenta, campo_2 RUBRO
27 FROM ]' || Lv_Table || q'[
28 WHERE codigo=4
29 AND campo_2 != 'ICE (12%)']';
30
31 OPEN C_DATOS FOR Lv_SQL;
32
33 loop
34 fetch c_datos into l_cuenta, l_rubro;
35 exit when c_datos%notfound;
36
37 INSERT INTO GSI_QC_CBS_CASOS_ERROR(CUENTA, ID_ESCENARIO, DATO_TMP_1)
38 VALUES(l_CUENTA, 'IdEscenario', 'DATA');
39 END LOOP;
40 COMMIT;
41
42 CLOSE C_DATOS;
43
44 EXCEPTION
45 WHEN OTHERS THEN
46 Pv_MsjError := SQLERRM;
47 END PROC_CAB_DET;
48 /
Procedure created.
Let's run it:
SQL> set serveroutput on;
SQL> declare
2 l_err varchar2(200);
3 begin
4 proc_cab_det('02', l_err);
5 dbms_output.put_line('error = ' || l_err);
6 end;
7 /
error =
PL/SQL procedure successfully completed.
SQL>
Replace " inside your lv_SQL string with doubled single quotes, ''

How to check if an oracle database has some PDB's and then print out the data to screen

My end goal is to query a database, check if v$pdb's exists and then if it does, query it. If it does not, move on and do something else. Basically I want a script that works with 11g and later versions too. I'm falling at the first fence really. I simply want this to output to screen. All it outputs though is "v_str".
SET FEEDBACK OFF;
SET SERVEROUTPUT ON;
declare
v_str varchar2(200);
v_str1 varchar2(200);
begin
v_str := 'select dbid, con_id, name into v_str1 from v$pdbs';
v_str1 := q'!begin dbms_output.put_line('v_str'); end;!';
Execute immediate v_str;
begin dbms_output.put_line(v_str1);
end;
/
Can anyone help me to get the output to prompt to screen...? Thanks!
A little conditional compilation should help out here
SQL> declare
2 has_container varchar2(1);
3 in_container varchar2(1);
4 begin
5 $IF DBMS_DB_VERSION.VER_LE_11_2
6 $THEN
7 has_container := 'N';
8 in_container := 'N';
9 $ELSE
10 has_container := case when to_number(sys_context('USERENV','CON_ID')) = 0 then 'N' else 'Y' end;
11 in_container := case when to_number(sys_context('USERENV','CON_ID')) > 1 then 'Y' else 'N' end;
12 $END
13 dbms_output.put_line('has_container='||has_container);
14 dbms_output.put_line('in_container='||in_container);
15
16 end;
17 /
has_container=Y
in_container=N
In this code
has_container = is the database multitenant (Y/N)
is_container = if the database IS multitenant, am I currently in the root or a pluggable
Then if you want a list, you can use a cursor loop
SQL> declare
2 has_container varchar2(1);
3 in_container varchar2(1);
4 begin
5 $IF DBMS_DB_VERSION.VER_LE_11_2
6 $THEN
7 has_container := 'N';
8 in_container := 'N';
9 $ELSE
10 has_container := case when to_number(sys_context('USERENV','CON_ID')) = 0 then 'N' else 'Y' end;
11 in_container := case when to_number(sys_context('USERENV','CON_ID')) > 1 then 'Y' else 'N' end;
12 if has_container = 'Y' and in_container = 'N' then
13 for i in ( select name from v$pdbs )
14 loop
15 dbms_output.put_line(i.name);
16 end loop;
17 end if;
18 $END
19 dbms_output.put_line('has_container='||has_container);
20 dbms_output.put_line('in_container='||in_container);
21
22 end;
23 /
PDB$SEED
PDB1
PDB2
has_container=Y
in_container=N
SQL>

oracle how catch error in sql query in cursor block

how can i catch error in sql query in block exception? In the example below (division by zero - select (5 / 0) as example from dual), the exception block is not executed.
FUNCTION getData(p_result out integer)
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR select (5 / 0) as example from dual;
p_result := 1;
RETURN my_cursor;
exception
WHEN OTHERS THEN
p_result := 0;
END getData;
You're catching the error at the wrong place. It is raised when function is called, not when it is created. Here's an example.
First, your function:
SQL> create or replace
2 FUNCTION getData(p_result out integer)
3 RETURN SYS_REFCURSOR
4 AS
5 my_cursor SYS_REFCURSOR;
6 BEGIN
7 OPEN my_cursor FOR select (5 / 0) as example from dual;
8
9 p_result := 1;
10 RETURN my_cursor;
11
12 exception
13 WHEN OTHERS THEN
14 p_result := 0;
15 END getData;
16 /
Function created.
Calling it; I'm just displaying the error message; you'd do something else.
SQL> declare
2 l_res integer;
3 rc sys_refcursor;
4 l_exam number;
5 begin
6 rc := getdata(l_res);
7 loop
8 fetch rc into l_exam;
9 exit when rc%notfound;
10 dbms_output.put_line(l_exam);
11 end loop;
12 close rc;
13 exception
14 when others then
15 dbms_output.put_line('Error: ' || sqlerrm);
16 end;
17 /
Error: ORA-01476: divisor is equal to zero
PL/SQL procedure successfully completed.
SQL>
-------Just User this function------
------------------------------------
FUNCTION getData(p_result out integer)
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR select (5 / NULLIF(0,0)) as example from dual;
p_result := 1;
RETURN my_cursor;
exception
WHEN OTHERS THEN
p_result := 0;
END getData;

Get column values from multi-line text file

How can I populate the columns with data from a text file, where each line is a different column? The text file looks like this:
Amsterdam Aalsmeerweg
Aalsmeerweg
14
Amsterdam
NL
1059NJ
0204122131
Amsterdam Bos en Lommerweg
Bos en Lommerweg
215
AMSTERDAM
NL
1055DT
0206847676
Amsterdam Ceintuurbaan
Ceintuurbaan
314
AMSTERDAM
NL
1072GL
0204705292
This post didn't help me.
My code looks like this:
set serveroutput on;
CREATE or replace DIRECTORY USER_DIR AS '/home/renejanssen/';
GRANT READ ON DIRECTORY USER_DIR TO PUBLIC;
declare
V1 VARCHAR2(200);
F1 UTL_FILE.FILE_TYPE;
f_name WINKEL.NAAM%type;
f_adres varchar2(255);
f_homenr WINKEL.HUISNR%TYPE;
f_city varchar2(100);
f_countrcode varchar(255);
f_zipcode WINKEL.POSTCODE%TYPE;
f_phonenr WINKEL.TELNR%TYPE;
v_counter number DEFAULT 1; --counter for ID
BEGIN
F1 := UTL_FILE.FOPEN('USER_DIR','test','R');
Loop
BEGIN
UTL_FILE.GET_LINE(F1,V1);
dbms_output.put_line(v_counter || ' = ' || V1);
EXCEPTION WHEN No_Data_Found THEN EXIT;
dbms_output.put_line('niets');
END;
f_name := substr(V1,1);
f_adres := substr(V1,1);
f_homenr := substr(V1,1);
f_countrcode := substr(V1,1);
f_zipcode := substr(V1,1);
insert INTO WINKEL (ID, NAAM, HUISNR, POSTCODE, TELNR )
values(v_counter, f_name, f_homenr, f_zipcode, f_phonenr);
v_counter := v_counter +1;
end loop;
IF UTL_FILE.IS_OPEN(F1) THEN
dbms_output.put_line('File is Open');
end if;
UTL_FILE.FCLOSE(F1);
END;
If each entry in the file always has seven lines as you've shown, followed by a blank line, you can do seven reads directly into your PL/SQL variables:
declare
v1 varchar2(200);
f1 utl_file.file_type;
f_name winkel.naam%type;
f_adres varchar2(255);
f_homenr winkel.huisnr%type;
f_city varchar2(100);
f_countrcode varchar(255);
f_zipcode winkel.postcode%type;
f_phonenr winkel.telnr%type;
v_counter number default 1; --counter for ID
begin
f1 := utl_file.fopen('D42','test','R');
loop
begin
utl_file.get_line(f1, f_name);
utl_file.get_line(f1, f_adres);
utl_file.get_line(f1, f_homenr);
utl_file.get_line(f1, f_city);
utl_file.get_line(f1, f_countrcode);
utl_file.get_line(f1, f_zipcode);
utl_file.get_line(f1, f_phonenr);
exception
when no_data_found then
exit;
dbms_output.put_line('niets');
end;
insert into winkel(id, naam, huisnr, postcode, telnr)
values (v_counter, f_name, f_homenr, f_zipcode, f_phonenr);
v_counter := v_counter +1;
begin
-- consume possible blank line; don't error as final entry may not have one
utl_file.get_line(f1, f_adres);
dbms_output.put_line('extra line: ' || f_adres);
exception
when no_data_found then
dbms_output.put_line('extra line: ' || sqlerrm);
null;
end;
end loop;
if utl_file.is_open(f1) then
dbms_output.put_line('File is Open');
end if;
utl_file.fclose(f1);
end;
/
With your data file that populates a table with:
select * from winkel;
ID NAAM HUISNR POSTCODE TELNR
---------- ---------------------------------------- ---------- ---------- --------------
1 Amsterdam Aalsmeerweg 14 1059NJ 0204122131
2 Amsterdam Bos en Lommerweg 215 1055DT 0206847676
3 Amsterdam Ceintuurbaan 314 1072GL 0204705292

Assign value to array from plsql block

I have the following code in Oracle Forms detail block
BEGIN
v_product_no := :detail_block.product_no;
Go_block('detail_block');
first_record;
--some if condition
WHILE :SYSTEM.last_record != 'TRUE' LOOP
next_record;
if(:detail_block.product_no = v_product_no) then
-- other condtions
end if;
END LOOP;
I would like to store v_product_no into a some kind of collection object so that I could compare with value of :detail_block.product_no.
How can I do this?
Edit 1
product_no will have values such as K1BATTERY, K2BATTERY, ZCATBATEERY etc.
So if K1BATTERY is same as :detail_block.product_no then proceed with next condition
Edit 2
Go_block('detail_block');
v_product_no := :detail_block.product_no;
v_products(v_product_no) := 1;
first_record;
WHILE :SYSTEM.last_record != 'TRUE' LOOP
if(v_products.exists(v_product_no)) then
alert('duplicate');
end if;
END LOOP;
END if;
Edit 3
Go_block('detail_block');
v_product_no := :detail_block.product_no;
v_products(v_product_no) := 1;
first_record;
-- condition
WHILE :SYSTEM.last_record = 'FALSE' LOOP
next_record;
v_product_no := :detail_block.product_no;
if(v_products.exists(v_product_no)) then
alert('duplicate');
else
v_products(v_product_no) := 1;
end if;
END LOOP;
END if;
Use pl/sql associative array to store already processed values.
declare
type t_processed is table of number(1) index by varchar2(100);
v_product_no varchar2(100); --hold the current value
v_products t_processed; --hold all processed values as keys
begin
v_product_no := :detail_block.product_no;
v_products(v_product_no) := 1; --create entry (v_product_no, 1)
...
--later in while
v_product_no := :detail_block.product_no;
if(v_products.exists(v_product_no)) then --entry exists
-- other conditions
else
v_products(v_product_no) := 1; --create entry (v_product_no, 1)
end if;
...
I think you are having Varying IN list of values in v_product_no variable.
You could do it in following way,
Test# 1
SQL> var product_no VARCHAR2(1000)
SQL> exec :product_no := 'K1BATTERY'
PL/SQL procedure successfully completed.
SQL>
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 v_product_no VARCHAR2(1000);
3 BEGIN
4 v_product_no := 'K1BATTERY, K2BATTERY, ZCATBATEERY';
5 IF :product_no IN (trim(regexp_substr(v_product_no, '[^,]+'))) THEN
6 DBMS_OUTPUT.PUT_LINE('FOUND A MATCH');
7 ELSE
8 DBMS_OUTPUT.PUT_LINE('NO MATCH FOUND');
9 END IF;
10 END;
11 /
FOUND A MATCH
PL/SQL procedure successfully completed.
Test# 2
SQL> var product_no VARCHAR2(1000)
SQL> exec :product_no := 'ABCD'
PL/SQL procedure successfully completed.
SQL>
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 v_product_no VARCHAR2(1000);
3 BEGIN
4 v_product_no := 'K1BATTERY, K2BATTERY, ZCATBATEERY';
5 IF :product_no IN (trim(regexp_substr(v_product_no, '[^,]+'))) THEN
6 DBMS_OUTPUT.PUT_LINE('FOUND A MATCH');
7 ELSE
8 DBMS_OUTPUT.PUT_LINE('NO MATCH FOUND');
9 END IF;
10 END;
11 /
NO MATCH FOUND
PL/SQL procedure successfully completed.
SQL>

Resources