Unable to get dbms_sql.column_value - oracle

I'm trying to read a query from a table and process it with DBMS_SQL package. It parses correctly. I can also see the columns, which occurs in a query. But I'm not able to fetch results. In debug mode It throws the exception while trying to getting dbms_sql.column_value (please see the code below).
/*--------------------------------------------------------------------------------------------------------------------*/
PROCEDURE MY_PROC( nCSV_EXP_CFG_ID IN NUMBER,nN1 IN NUMBER DEFAULT null )
/*--------------------------------------------------------------------------------------------------------------------*/
as
l_ntt_desc_tab dbms_sql.desc_tab;
nCursorId INTEGER;
nColCnt INTEGER;
nRowCnt INTEGER;
rCSV_EXP_CFG CSV_EXP_CFG%ROWTYPE;
TYPE rowArray IS VARRAY(20) OF VARCHAR2(255);
colVal rowArray;
BEGIN
SELECT * INTO rCSV_EXP_CFG
FROM CSV_EXP_CFG
WHERE
CSV_EXP_CFG_ID = nCSV_EXP_CFG_ID;
nCursorId:=dbms_sql.open_cursor;
dbms_sql.parse(nCursorId, rCSV_EXP_CFG.EXPORT_TABLE, dbms_sql.native);
IF nN1 IS NOT NULL THEN DBMS_SQL.BIND_VARIABLE (nCursorId, 'n1', nN1); END IF;
dbms_sql.describe_columns(nCursorId, nColCnt, l_ntt_desc_tab);
FOR i IN 1..nColCnt LOOP
DBMS_OUTPUT.PUT_LINE( l_ntt_desc_tab(i).col_name);
--DBMS_SQL.DEFINE_COLUMN(nCursorId, i, colVal(i), 255);
END LOOP;
nRowCnt:=dbms_sql.execute(nCursorId);
LOOP
EXIT WHEN dbms_sql.fetch_rows(nCursorId) = 0;
FOR i IN 1..nColCnt LOOP
--here I'm getting the exception
dbms_sql.column_value(nCursorId, i, colVal(i));
END LOOP;
END LOOP;
Dbms_sql.close_cursor(nCursorId);
EXCEPTION WHEN OTHERS THEN
NULL;
END MY_PROC;
What am I doing wrong?

Related

NO DATA FOUND oracle using cursor

I have been searching online using different solution suggestion to handle no data in this code but to no avail. how can I handle the exception if no data is found. How can I solve this problem. I am not an expert in oracle though!
DECLARE
nCheckOption INT;
no_data_found EXCEPTION;
CURSOR TYPE_cursor IS
SELECT
D_NAL_REF.TRANS
, D_NAL_REF.INJ
, D_NAL_REF.REF
FROM D_NAL_REF D_NAL_REF
WHERE D_NAL_REF.REF IN
(SELECT AG_REF.REF
FROM AG_REF A_REF
WHERE A_REF.DESCEND_REF = 10
);
BEGIN
FOR rec IN TYPE_cursor
LOOP
nCheckOption := 0;
SELECT 1
INTO nCheckOption
FROM PERSON_TYPE WHERE TRANS = rec.TRANS AND INJ = rec.INJ;
IF nCheckOption = 1 THEN
UPDATE PERSON_TYPE
SET PERSON_TYPE.TYPE = rec.REF
WHERE TRANS = rec.TRANS
AND PERSON_TYPE.INJ = rec.INJ;
END IF;
EXCEPTION
WHEN no_data_found
THEN
DBMS_OUTPUT.PUT_LINE ('Trapped the error!?');
END LOOP;
END;
/
Rewrite your code to eliminate the inner SELECT, which is the only place in your code where I can see that a NO_DATA_FOUND exception could possibly be raised:
BEGIN
FOR rec IN (SELECT d.TRANS,
d.INJ,
d.REF
FROM D_NAL_REF d
WHERE d.REF IN (SELECT a.REF
FROM AG_REF a
WHERE a.DESCEND_REF = 10) AND
(d.TRANS, d.INJ) IN (SELECT DISTINCT TRANS, INJ
FROM PERSON_TYPE))
LOOP
UPDATE PERSON_TYPE
SET TYPE = rec.REF
WHERE TRANS = rec.TRANS AND
INJ = rec.INJ;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Trapped the error!?');
END;
I think you need to find if cursor contains any record or not. If cursor is empty then it must return that error message written in exception block.
Or you want to print error message if update statement do not find any record to update.
Here is the pseudo code.
Declare
ncheckoption number := 0;
Cursor type_cursor is ....
Begin
For rec in type_cursor loop
ncheckoption := ncheckoption + 1;
Update ...
If sql%rowcount = 0 then
Dbms_output.put_line('error message, if you want here in case no record found in table to update');
-- loop will continue
-- if you want loop to break then issue exit statement here
End if;
End loop;
If ncheckoption = 0 then
Dbms_output.put_line('error message you want to print in case cursor is empty');
End if;
End;
/
Cheers!!

How to handle cursor exception when the select query returns "zero" records

How to handle cursor exception when the select query returns "zero" records
I have a cursor in a procedure, and after cursor initialization I'm iterating through the cursor to access the data from it.
But the problem is when the cursor select query returns 0 records then it throws exception
ORA-06531: Reference to uninitialized collection.
How to handle this exception?
---procedure code
create or replace PROCEDURE BIQ_SECURITY_REPORT
(out_chr_err_code OUT VARCHAR2,
out_chr_err_msg OUT VARCHAR2,
out_security_tab OUT return_security_arr_result ,
)
IS
l_chr_srcstage VARCHAR2 (200);
lrec return_security_report;
CURSOR cur_security_data IS
SELECT
"ID" "requestId",
"ROOM" "room",
"FIRST_NAME" "FIRST_NAME",
"LAST_NAME" "LAST_NAME",
FROM
"BI_REQUEST_CATERING_ACTIVITY" ;
TYPE rec_security_data IS TABLE OF cur_security_data%ROWTYPE
INDEX BY PLS_INTEGER;
l_cur_security_data rec_security_data;
begin
OPEN cur_security_data;
LOOP
FETCH cur_security_data
BULK COLLECT INTO l_cur_security_data
LIMIT 1000;
EXIT WHEN l_cur_security_data.COUNT = 0;
lrec := return_security_report();
out_security_tab := return_security_arr_result(return_security_report());
out_security_tab.delete;
FOR i IN 1 .. l_cur_security_data.COUNT
LOOP
BEGIN
l_num_counter := l_num_counter + 1;
lrec := return_security_report();
lrec.requestid := l_cur_security_data(i).requestId ; lrec.room := l_cur_security_data(i).room ; lrec.firstName := l_cur_security_data(i).firstName ;
IF l_num_counter > 1
THEN
out_security_tab.extend();
out_security_tab(l_num_counter) := return_security_report();
ELSE
out_security_tab := return_security_arr_result(return_security_report());
END IF;
out_security_tab(l_num_counter) := lrec;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('Error occurred : ' || SQLERRM);
END;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('HERE INSIIDE OTHERS' || SQLERRM);
END;
Can you please explain how handle it.
You must be using out_security_tab, which is an output parameter in some other code where the procedure is called.
In your procedure, If cursor returns zero rows then the loop will not be executed and your code will not even initialize the out_security_tab which will lead to the error that you are facing.
There is a simple way to avoid:
initialize out_security_tab outside the loop -- which will definitely initialize it
You can create one out variable containing details as Y or N based on if cursor rows count -- Not recommended
Cheers!!

Cannot insert Third column of data

I am noob in PL/SQL I just start learning and I want to create small peace of software that insert data from .CVS file to Oracle database.
And I stuck in part where I grab data from .CVS file.
I my CVS there are three column: Number_Policy,Contact, Agency
Number_Policy,Contact is catch success, but Agency can not be catched and I dont know why
declare
import_file text_io.file_type;
export_file text_io.file_type;
import_file_name varchar2(1000);
export_file_name varchar2(1000);
import_log_file text_io.file_type;
import_log_file_name varchar2(1000);
vec_importovano number;
brojac number;
brojac_redova number;
linebuf varchar2(10000);
p_rbr varchar2(20);
p_polica varchar2(20);
p_banka VARCHAR2(50);
p_kontakt varchar2(20);
kraj_fajla number;
begin
brojac_redova:=0;
import_file_name := :Global.Lokacija_prenosa||:import.naziv_fajla||:Global.Ekstenzija_prenosa;
import_file := text_io.fopen(import_file_name,'r');
delete from zivot_trajni_nalog_ponude where banka is not null;
commit;
kraj_fajla := 0;
while kraj_fajla = 0 loop
begin
brojac_redova:=brojac_redova+1;
text_io.get_line(import_file, linebuf);
if brojac_redova >= 2 then
p_polica:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
-- message(p_polica);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
-- message(p_banka);
--p_kontakt:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
-- message(p_kontakt);
/*
p_rbr:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
-- message(p_rbr);
p_polica:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
-- message(p_polica);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
message(p_banka);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,3)+1, instr(linebuf,';',1,4) - instr(linebuf,';',1,3)-1);
message(p_kontakt);
*/
if vec_importovano = 0 then
insert into ZIVOT_TRAJNI_NALOG_PONUDE
(BROJ_POLICE,BROJ_PONUDE)
values(
p_polica,
--p_rbr,
p_kontakt);
-- p_banka);
commit;
end if;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN kraj_fajla := 1;
end;
end loop;
IF p_polica IS NOT NULL
THEN
update zivot_trajni_nalog_ponude set BROJ_POLICE=rownum;
commit;
END IF;
text_io.fclose(import_file);
message ('Uspjesno zavrseno');
end;
As you can see from code there is error somewhere here
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
-- message(p_banka);
After I disable this column the problem is that column p_polica and p_kontakt can't be inserted into database.
If anyone know where I made mistake I would be very thankful for any help.
Looks like linebuf has only two semicolons. This piece of code worked in my short test:
if instr(linebuf,';',1,3) > 0 then
p_banka := substr(linebuf,
instr(linebuf,';',1, 2) + 1,
instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
else
p_banka := substr(linebuf,
instr(linebuf,';',1, 2) + 1);
end if;

How to populate TABLE OF RECORDS with rows of 2 levels parent-child

I have a table with rows describing a tree, columns are:
(column child_num is unique and used as primary key)
TABLE items_tree (
child_num number,
parent_ref varchar2(10),
child_ref varchar2(10)
);
TYPE item_rec_type IS RECORD (
item_id NUMBER,
spaces_number NUMBER,
parent_ref VARCHAR2(10),
child_ref VARCHAR2(10)
);
TYPE tree_table_type IS TABLE OF item_rec_type%ROWTYPE
INDEX BY BINARY_INTEGER;
table_tree tree_table_type; -- table of all items
Example data for table items_tree (values of child_num are not relevant):
parent_ref child_ref
---------------------------
null Abraham
Abraham Isaac
Abraham Ishmael
Isaac Jakob
Jakob Yehuda
Jakob Josef
Jakob Benjamin
Yehuda David
Josef Efraim
Josef Menashe
David Solomon
Solomon Isaiah
Isaiah Jeremiah
I need to populate table_tree records from items_tree table. To do so, I am using a package, the item_rec_type, tree_table_type, table_tree are defined in it and two procedures: print_tree which retrieves the ROOT items of the tree, starts the process and prints the tree from table_tree. Second procedure get_items_by_parent_recursively is recursive procedure that retrieves all the items or a parent item, e.g. calling get_items_by_parent_recursively('Abraham') will add Isaac and Ishmael to table_tree.
The cursor is declared in the package body:
CURSOR get_children_cur(c_parent in varchar2(10))
IS
SELECT parent_ref, child_ref
FROM items_tree
WHERE parent_ref = c_parent
ORDER BY 1, 2;
The code in get_items_by_parent_recursively that retrieves the items for the parent:
procedure get_items_by_parent_recursively(p_parent in VARCHAR2(10), p_spaces_number in NUMBER )
AS
l_spaces_number NUMBER := 0;
l_child VHARCHAR2(10);
l_parent VHARCHAR2(10);
BEGIN
l_spaces_number := p_spaces_number + 3;
OPEN get_children_cur(p_parent);
LOOP
FETCH get_children_cur INTO l_parent, l_child;
EXIT WHEN get_children_cur%NOTFOUND;
IF (l_child is not null) THEN
v_row_number := v_row_number + 1;
tree_table(v_row_number).row_num := v_row_number;
tree_table(v_row_number).spaces_number := l_spaces_number;
tree_table(v_row_number).parent_ref := l_parent;
tree_table(v_row_number).child_ref := l_child;
-- Calling procedure recursively
get_items_by_parent_recursively( l_child, l_spaces_number );
END IF;
END LOOP;
CLOSE get_children_cur;
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN
DBMS_OUTPUT.put_line(' Exception -- CURSOR_ALREADY_OPEN');
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.put_line(' Exception -- INVALID_CURSOR');
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.put_line(' Exception -- INVALID_NUMBER');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line(' Exception -- NO_DATA_FOUND');
WHEN PROGRAM_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- PROGRAM_ERROR');
WHEN ROWTYPE_MISMATCH THEN
DBMS_OUTPUT.put_line(' Exception -- ROWTYPE_MISMATCH');
WHEN STORAGE_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- STORAGE_ERROR');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.put_line(' Exception -- TOO_MANY_ROWS');
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- VALUE_ERROR');
END get_items_by_parent_recursively;
Running this procedure I am getting the exception: CURSOR_ALREADY_OPEN.
I have searched for a reply, but none came close to what I need. I will appreciate any ideas.
I will try to make the cursor get_children_cur part of the recursive procedure.
As #vmachan said, you need to move the cursor definition into the procedure. While you have it in the package specification or body, but outside the procedure, there is one instance of it which is global to the session. Each call to your procedure attempts to open the same cursor; the initial call from print_tree succeeds, and your table is populated with 'Abraham'; but then the recursive call tries to re-open it and gets the CURSOR_ALREADY_OPEN exception, and stops.
Moving the cursor into the procedure means each call/iteration has its own independent copy. Cleaning up naming and various other issues, this then works:
procedure get_items_by_parent(p_parent in VARCHAR2, p_spaces_number in NUMBER)
AS
l_spaces_number NUMBER := 0;
l_child VARCHAR2(10);
l_parent VARCHAR2(10);
CURSOR get_children_cur(p_parent in varchar2) IS
SELECT parent_item, child_item
from items_tree
where parent_item = p_parent
or (p_parent is null and parent_item is null);
BEGIN
l_spaces_number := p_spaces_number + 3;
OPEN get_children_cur(p_parent);
LOOP
FETCH get_children_cur INTO l_parent, l_child;
EXIT WHEN get_children_cur%NOTFOUND;
IF (l_child is not null) THEN
v_row_number := v_row_number + 1;
table_tree(v_row_number).item_id := v_row_number;
table_tree(v_row_number).spaces_number := l_spaces_number;
table_tree(v_row_number).parent_item_ref := l_parent;
table_tree(v_row_number).item_ref := l_child;
-- Calling procedure recursively
get_items_by_parent( l_child, l_spaces_number );
END IF;
END LOOP;
CLOSE get_children_cur;
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN
DBMS_OUTPUT.put_line(' Exception -- CURSOR_ALREADY_OPEN');
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.put_line(' Exception -- INVALID_CURSOR');
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.put_line(' Exception -- INVALID_NUMBER');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line(' Exception -- NO_DATA_FOUND');
WHEN PROGRAM_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- PROGRAM_ERROR');
WHEN ROWTYPE_MISMATCH THEN
DBMS_OUTPUT.put_line(' Exception -- ROWTYPE_MISMATCH');
WHEN STORAGE_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- STORAGE_ERROR');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.put_line(' Exception -- TOO_MANY_ROWS');
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.put_line(' Exception -- VALUE_ERROR');
END get_items_by_parent;
Inventing a print_tree based on what you describe:
procedure print_tree is
begin
get_items_by_parent(null, 0);
for i in 1..table_tree.count loop
dbms_output.put_line(to_char(table_tree(i).item_id, '99999') || ' '
|| lpad(' ', table_tree(i).spaces_number, ' ')
|| table_tree(i).item_ref);
end loop;
end print_tree;
... calling that now works, and produces 13 indented records:
1 Abraham
2 Isaac
3 Jakob
4 Yehuda
5 David
6 Solomon
7 Isaiah
8 Jeremiah
9 Josef
10 Efraim
11 Menashe
12 Benjamin
13 Ishmael
As #XING said, you can get the same result more simply with a different for of cursor loop:
procedure get_items_by_parent(p_parent in VARCHAR2, p_spaces_number in NUMBER)
AS
l_spaces_number NUMBER := 0;
CURSOR get_children_cur(p_parent in varchar2) IS
SELECT parent_item, child_item
from items_tree
where child_item is not null
and (parent_item = p_parent
or (p_parent is null and parent_item is null));
BEGIN
l_spaces_number := p_spaces_number + 3;
FOR r IN get_children_cur(p_parent)
LOOP
v_row_number := v_row_number + 1;
table_tree(v_row_number).item_id := v_row_number;
table_tree(v_row_number).spaces_number := l_spaces_number;
table_tree(v_row_number).parent_item_ref := r.parent_item;
table_tree(v_row_number).item_ref := r.child_item;
-- Calling procedure recursively
get_items_by_parent( r.child_item, l_spaces_number );
END LOOP;
END get_items_by_parent;
or even:
procedure get_items_by_parent(p_parent in VARCHAR2, p_spaces_number in NUMBER)
AS
BEGIN
FOR r IN (
SELECT parent_item, child_item
from items_tree
where child_item is not null
and (parent_item = p_parent
or (p_parent is null and parent_item is null)))
LOOP
v_row_number := v_row_number + 1;
table_tree(v_row_number).item_id := v_row_number;
table_tree(v_row_number).spaces_number := p_spaces_number + 3;
table_tree(v_row_number).parent_item_ref := r.parent_item;
table_tree(v_row_number).item_ref := r.child_item;
-- Calling procedure recursively
get_items_by_parent( r.child_item, p_spaces_number + 3 );
END LOOP;
END get_items_by_parent;
Of course, you don't need to use PL/SQL or a table at all, you can use a hierarchical query:
select rownum, lpad(' ', level * 3, ' ') || child_item as item
from items_tree
start with parent_item is null
connect by parent_item = prior child_item
order siblings by child_num;
ROWNUM ITEM
---------- --------------------------------------------------
1 Abraham
2 Isaac
3 Jakob
4 Yehuda
5 David
6 Solomon
7 Isaiah
8 Jeremiah
9 Josef
10 Efraim
11 Menashe
12 Benjamin
13 Ishmael
but presumably this is a PL/SQL exercise. If you aren't required to use a recursive procedure you could still populate your table from a similar query, using bulk collect.

ora-01422 error by a procedure

Below code throwing ORA-01422 error. As my code uses select ... into I come to know it is fetching more than one row from the table but how can I overcome this by eliminating select into statement. Here is the code:
PROCEDURE Call_Transaction ( Transaction_Name Varchar2, Transaction_Type Varchar2, Form_Open_Type Varchar2 ) IS
BEGIN
Declare
M_Transaction_Name U_Transaction_Master.Transaction_Name%Type := Upper(Transaction_Name);
M_Transaction_Cd U_Transaction_Master.Transaction_Cd%Type;
T_Transaction_Cd U_Transaction_Master.Transaction_Cd%Type;
Begin
Select Transaction_Cd Into M_Transaction_Cd From U_Transaction_Master
Where Transaction_Name = M_Transaction_Name ;
Begin
Select Transaction_Cd Into T_Transaction_Cd From U_User_Wise_Transactions
Where Login_Cd = :Global.Login_Cd And Transaction_Cd = M_Transaction_Cd And
Inst_Cd = :Global.Company_Cd And
To_Char(Valid_Upto_Date,'DD-MM-YYYY') = '31-12-9999';
If Transaction_Type = 'FORM' And Upper(Form_Open_Type) = 'CALL_FORM' Then
DECLARE
id FormModule;
BEGIN
id := Find_Form(M_Transaction_Name); --<Replace your form name>--
IF Id_Null(id) THEN
Call_Form(:Global.Forms_Path||M_Transaction_Name||'.Fmx');
ELSE
Go_Form(Id) ;
END IF ;
END ;
Elsif Transaction_Type = 'FORM' And Upper(Form_Open_Type) = 'OPEN_FORM' Then
Open_Form(:Global.Forms_Path||M_Transaction_Name||'.Fmx');
Elsif Transaction_Type = 'REPORT' And Upper(Form_Open_Type) = 'RUN_PRODUCT' Then
Declare
Pl_Id ParamList;
Begin
Pl_Id := Get_Parameter_List('tmpdata');
IF NOT Id_Null(Pl_Id) THEN
Destroy_Parameter_List( Pl_Id );
END IF;
Pl_Id := Create_Parameter_List('tmpdata');
ADD_Parameter(pl_id,'Inst_Cd',TEXT_PARAMETER,:GLOBAL.Company_Cd);
ADD_Parameter(pl_id,'Ac_Year_Cd',TEXT_PARAMETER,:GLOBAL.Ac_Year_Cd);
ADD_Parameter(Pl_Id,'INST_NAME',TEXT_PARAMETER, :Global.Company_name);
ADD_Parameter(Pl_Id,'ADDRESS',TEXT_PARAMETER, :Global.Address);
ADD_Parameter(pl_id,'FOOTER',TEXT_PARAMETER,:GLOBAL.Footer);
Run_Product(REPORTS,:Global.Reports_Path||M_Transaction_Name, SYNCHRONOUS, RUNTIME,
FILESYSTEM, Pl_Id, NULL);
End;
End If;
Exception
When No_Data_Found Then
Message('Sorry..., You Do Not Have Authorization For : '||M_Transaction_Cd||' Transaction Code...');
Raise Form_Trigger_Failure;
End;
Exception
When No_Data_Found Then
Message('The Transaction Cd Not Exists In Transaction Master, Please Contact Administrator...');
Raise Form_Trigger_Failure;
End;
END;
How can I rewrite the code to resolve ORA-01422 error?
First, you need to change exception handling logic:
enclose in begin ... exception ... end only part that really can
through exception;
handle too_many_rows exception
.
PROCEDURE Call_Transaction ( Transaction_Name Varchar2, Transaction_Type Varchar2, Form_Open_Type Varchar2 ) IS
BEGIN
Declare
M_Transaction_Name U_Transaction_Master.Transaction_Name%Type := Upper(Transaction_Name);
M_Transaction_Cd U_Transaction_Master.Transaction_Cd%Type;
T_Transaction_Cd U_Transaction_Master.Transaction_Cd%Type;
Begin
-- 1st select with error analysis
begin
Select Transaction_Cd Into M_Transaction_Cd From U_Transaction_Master
Where Transaction_Name = M_Transaction_Name ;
exception
when No_Data_Found then begin
Message('The Transaction Cd Not Exists In Transaction Master, Please Contact Administrator...');
Raise Form_Trigger_Failure;
end;
when too_many_rows then begin
-- What really must be done in this case?
Message('There are too many Transaction Cd's with passed name In Transaction Master, Please Contact Administrator...');
Raise Form_Trigger_Failure;
end;
end;
-- 2nd select with error analysis
begin
Select Transaction_Cd Into T_Transaction_Cd From U_User_Wise_Transactions
Where Login_Cd = :Global.Login_Cd And Transaction_Cd = M_Transaction_Cd And
Inst_Cd = :Global.Company_Cd And
To_Char(Valid_Upto_Date,'DD-MM-YYYY') = '31-12-9999';
Exception
When No_Data_Found Then begin
Message('Sorry..., You Do Not Have Authorization For : '||M_Transaction_Cd||' Transaction Code...');
Raise Form_Trigger_Failure;
end;
When too_many_rows Then begin
-- What really must be done in this case?
Message('Sorry..., there are some misconfiguration in Authorization Settings For : '||M_Transaction_Cd||' Transaction Code. Please contact Administrator.');
Raise Form_Trigger_Failure;
end;
End;
If Transaction_Type = 'FORM' And Upper(Form_Open_Type) = 'CALL_FORM' Then
---[... all other code skipped ...]---
End If;
END;
After refactoring you need to answer a question about what really must be performed in situations when more than one row found and handle it according to nature of implemented task.
If you worried about method that you can use to detect presence of values and determine it's count then you may look at this question on StackOverflow.
In oracle, you can keep the select into statement and limit the number of rows using ROWNUM:
Select Transaction_Cd Into M_Transaction_Cd From U_Transaction_Master
Where Transaction_Name = M_Transaction_Name
and ROWNUM < 2;

Resources