to create a particular procedure [duplicate] - sql

How to use put function.my procedure is not compiling with put. but putline is working fine. i want to print in the same line

Here's an example of code which uses the UTL_FILE.PUT and UTL_FILE.PUT_LINE calls:
declare
fHandle UTL_FILE.FILE_TYPE;
begin
fHandle := UTL_FILE.FOPEN('my_directory', 'test_file', 'w');
UTL_FILE.PUT(fHandle, 'This is the first line');
UTL_FILE.PUT(fHandle, 'This is the second line');
UTL_FILE.PUT_LINE(fHandle, 'This is the third line');
UTL_FILE.FCLOSE(fHandle);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception: SQLCODE=' || SQLCODE || ' SQLERRM=' || SQLERRM);
RAISE;
end;
The output from this looks like:
This is the first lineThis is the second lineThis is the third line
Share and enjoy.

Here is a robust function for using UTL_File.putline that includes the necessary error handling. It also handles headers, footers and a few other exceptional cases.
PROCEDURE usp_OUTPUT_ToFileAscii(p_Path IN VARCHAR2, p_FileName IN VARCHAR2, p_Input IN refCursor, p_Header in VARCHAR2, p_Footer IN VARCHAR2, p_WriteMode VARCHAR2) IS
vLine VARCHAR2(30000);
vFile UTL_FILE.file_type;
vExists boolean;
vLength number;
vBlockSize number;
BEGIN
UTL_FILE.fgetattr(p_path, p_FileName, vExists, vLength, vBlockSize);
FETCH p_Input INTO vLine;
IF p_input%ROWCOUNT > 0
THEN
IF vExists THEN
vFile := UTL_FILE.FOPEN_NCHAR(p_Path, p_FileName, p_WriteMode);
ELSE
--even if the append flag is passed if the file doesn't exist open it with W.
vFile := UTL_FILE.FOPEN(p_Path, p_FileName, 'W');
END IF;
--GET HANDLE TO FILE
IF p_Header IS NOT NULL THEN
UTL_FILE.PUT_LINE(vFile, p_Header);
END IF;
UTL_FILE.PUT_LINE(vFile, vLine);
DBMS_OUTPUT.PUT_LINE('Record count > 0');
--LOOP THROUGH CURSOR VAR
LOOP
FETCH p_Input INTO vLine;
EXIT WHEN p_Input%NOTFOUND;
UTL_FILE.PUT_LINE(vFile, vLine);
END LOOP;
IF p_Footer IS NOT NULL THEN
UTL_FILE.PUT_LINE(vFile, p_Footer);
END IF;
CLOSE p_Input;
UTL_FILE.FCLOSE(vFile);
ELSE
DBMS_OUTPUT.PUT_LINE('Record count = 0');
END IF;
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN
DBMS_OUTPUT.PUT_LINE ('invalid_path');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.INVALID_MODE THEN
DBMS_OUTPUT.PUT_LINE ('invalid_mode');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.INVALID_FILEHANDLE THEN
DBMS_OUTPUT.PUT_LINE ('invalid_filehandle');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.INVALID_OPERATION THEN
DBMS_OUTPUT.PUT_LINE ('invalid_operation');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.READ_ERROR THEN
DBMS_OUTPUT.PUT_LINE ('read_error');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.WRITE_ERROR THEN
DBMS_OUTPUT.PUT_LINE ('write_error');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN UTL_FILE.INTERNAL_ERROR THEN
DBMS_OUTPUT.PUT_LINE ('internal_error');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('other write error');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
END;

You can check the below example of how to log/write using utl_file in PL/SQL.
DECLARE
fhandle utl_file.file_type;
BEGIN
fhandle := utl_file.fopen(
'UTL_DIR_STACKOVERFLOW'-- File location
, 'Check_Logging.txt' -- File name
, 'a' -- Open mode: a = append, w = write
);
utl_file.put(fhandle, 'Stackoverflow' );
utl_file.fclose(fhandle);
END;
Problems you can face-
Invalid directory object
Then you can create your own directory object and use the below query.
create or replace directory UTL_DIR_STACKOVERFLOW as '/tmp/';

CREATE OR REPLACE PROCEDURE SP_EXPORT_TO_CSV(P_OWNER VARCHAR2,
P_OBJECT_NAME VARCHAR2,
P_FILE_NAME VARCHAR2 --,
-- P_DELIMITED CHAR
) AS
-- declaration
TYPE C_DATA_CURSOR IS REF CURSOR;
C_DATA C_DATA_CURSOR;
v_file UTL_FILE.FILE_TYPE;
V_COLUMNS VARCHAR2(32767);
X VARCHAR2(32767);
V_FILE_NAME VARCHAR2(2000);
V_OWNER VARCHAR2(100);
V_OBJECT_NAME VARCHAR2(1000);
V_SQL VARCHAR2(32767);
V_DELIMITED VARCHAR2(10);
BEGIN
-- set value
V_FILE_NAME := P_FILE_NAME;
V_OBJECT_NAME := P_OBJECT_NAME;
V_OWNER := P_OWNER;
--V_DELIMITED:=P_DELIMITED;
SELECT REPLACE(LISTAGG(COLUMN_NAME, '|') WITHIN
GROUP(ORDER BY COLUMN_ID),
'|',
' || ' || '''|''' || ' || ')
INTO V_COLUMNS
FROM ALL_TAB_COLUMNS W
WHERE W.TABLE_NAME = V_OBJECT_NAME
AND W.OWNER = V_OWNER
ORDER BY COLUMN_ID;
-- SET OUTPUT PARAMETER --'EXPORTED_TO_TEXT_LOCATION'
v_file := UTL_FILE.FOPEN(location => 'MYLOCATION',
filename => V_FILE_NAME,
open_mode => 'w',
max_linesize => 32767);
UTL_FILE.PUT_LINE(v_file, REPLACE(V_COLUMNS, ' || ''|'' || ', '|'));
X := 'SELECT ' || V_COLUMNS || ' AS RECORD FROM ' || V_OWNER || '.' ||
V_OBJECT_NAME;
OPEN C_DATA FOR X;
LOOP
FETCH C_DATA
INTO V_SQL;
EXIT WHEN C_DATA%NOTFOUND;
UTL_FILE.PUT_LINE(v_file, V_SQL);
END LOOP;
CLOSE C_DATA;
UTL_FILE.FCLOSE(v_file);
END;

Related

Make the declared variable inside a trigger append its value if more than one condition is met

Well I was writing a trigger and I wanted that the declared variable v_message to append every time the condition is met. So for example if the first two statements are met the v_message should be something like "Invalid account Invalid amount". I must also find a way to separate these two messages by a space if the v_message already contains some sort of an error message as it wont be readable if you had something like this "Invalid accountInvalid amount".
CREATE OR REPLACE TRIGGER checkPayments
BEFORE INSERT ON tbl_payments
FOR EACH ROW
DECLARE
v_message VARCHAR(100 CHAR);
v_is_valid CHAR(1) := 'N';
BEGIN
IF getActiveUser(getOrderUsername(:new.order_id)) = 0
THEN v_message := 'Invalid account';
ELSIF isValidAmount(:new.payment_amount) = 0
THEN v_message := 'Invalid amount';
ELSIF checkOrderExist(:new.order_id) = 0
THEN v_message := 'Invalid order ID';
ELSIF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id)
THEN v_message := 'Payment exceeds total';
ELSE v_message := 'OK' ;
v_is_valid := 'Y';
END IF;
:new.payment_id:= seq_payment_id.nextval;
:new.payment_date:= LOCALTIMESTAMP;
:new.payment_message := v_message;
:new.is_valid := v_is_valid;
END;
/
CREATE OR REPLACE TRIGGER checkPayments
BEFORE INSERT ON tbl_payments
FOR EACH ROW
DECLARE
v_message VARCHAR(100 CHAR);
v_is_valid CHAR(1) := 'N';
BEGIN
v_is_valid := 'Y';
IF getActiveUser(getOrderUsername(:new.order_id)) = 0
THEN v_message := 'Invalid account';
v_is_valid := 'N';
END IF;
IF isValidAmount(:new.payment_amount) = 0
THEN v_message := v_message || ' Invalid amount';
v_is_valid := 'N';
END IF;
IF checkOrderExist(:new.order_id) = 0
THEN v_message := v_message || ' Invalid order ID';
v_is_valid := 'N';
END IF;
IF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id)
THEN v_message := v_message || ' Payment exceeds total';
v_is_valid := 'N';
END IF;
IF v_is_valid = 'Y'
THEN v_message := 'OK' ;
END IF;
:new.payment_id:= seq_payment_id.nextval;
:new.payment_date:= LOCALTIMESTAMP;
:new.payment_message := trim(v_message);
:new.is_valid := v_is_valid;
END;
/

preparing sql dynamically in oracle stored procedure

I have 3 input parameters,based on values of each input parameter i have to prepare the SQL in procedure dynamically. I am doing below way but it is failing, if the parameter value is null,then i have to exclude that from the where clause.
IN Parameters:
empid in varchar2 || empname IN varchar2 || empsal IN varchar2
SELECT
EMP_NAME
INTO
V_EMP_NAME
FROM
EMPLOYEE
WHERE
( EMP_ID = EMPID
OR ( EMP_ID IS NULL
AND EMPID IS NULL ) )
AND ( EMP_NAME = EMPNAME
OR ( EMP_NAME IS NULL
AND EMPNAME IS NULL ) )
AND ( EMP_SAL = EMPSAL
OR ( EMP_SAL IS NULL
AND EMPSAL IS NULL ) );
After updates i modified the query like below,it is compiled but giving run time errors saying that ORA-00933: SQL command not properly ended on just before EXECUTE IMMEDIATE
V_SQL :='SELECT EMP_NAME INTO V_empname FROM employee WHERE ';
BEGIN
IF(EMPID IS NOT NULL) THEN
V_SQL := V_SQL || ' emp_id='||EMPID;
END IF;
IF(EMPNAME IS NOT NULL) THEN
V_SQL := V_SQL || ' AND emp_name='||EMPNAME;
END IF;
IF(V_empsalIS NOT NULL) THEN
V_SQL := V_SQL || ' AND emp_sal='||empsal;
V_SQL := V_SQL ||' AND ACTIVE =''Y''' ;
END IF;
EXECUTE IMMEDIATE V_SQL;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_check:= '' ;
END;
Here you are another alternative:
V_SQL_WHERE := null;
V_SQL :='SELECT EMP_NAME INTO V_empname FROM employee';
BEGIN
IF(EMPID IS NOT NULL) THEN
V_SQL_WHERE := V_SQL_WHERE || ' emp_id='||EMPID;
END IF;
IF(EMPNAME IS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' emp_name='||EMPNAME;
END IF;
IF(V_empsalIS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' emp_sal=' || empsal;
V_SQL_WHERE := V_SQL_WHERE || ' AND ACTIVE =''Y''' ;
END IF;
IF (V_SQL_WHERE is not null) then
V_SQL := V_SQL || ' WHERE ' || V_SQL_WHERE;
end if;
EXECUTE IMMEDIATE V_SQL;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_check:= '' ;
END;
Something like this: (Not tested, but just an idea)
BEGIN
IF EMPID IS NOT NULL
THEN
CLAUSE1 := 'EMP_ID = EMPID';
ELSE
CLAUSE1 := '1=1';
END IF;
IF EMPNAME IS NOT NULL
THEN
CLAUSE2 := 'EMP_NAME = EMPNAME';
ELSE
CLAUSE2 := '1=1';
END IF;
IF EMPSAL IS NOT NULL
THEN
CLAUSE3 := 'EMP_SAL = EMPSAL';
ELSE
CLAUSE3 := '1=1';
END IF;
IF ( EMPSAL IS NULL
AND EMPNAME IS NULL
AND EMPID IS NOT NULL )
THEN
CLAUSE1 := '1=0';
CLAUSE2 := '1=0';
CLAUSE3 := '1=0';
END IF;
QUERY_STR :=
' SELECT EMP_NAME INTO V_EMP_NAME FROM EMPLOYEE WHERE'
|| CLAUSE1
|| ' AND '
|| CLAUSE2
|| ' AND '
|| CLAUSE3;
END;
You can create one from scratch, including if's and elses, or you can use a package called plsql-utils, the SQL_BUILDER_PKG. It does the whole work for you.
Have a look on SQL utilities
http://code.google.com/p/plsql-utils/
Eg:
declare
l_my_query sql_builder_pkg.t_query;
l_sql varchar2(32000);
begin
sql_builder_pkg.add_select (l_my_query, 'ename');
sql_builder_pkg.add_select (l_my_query, 'sal');
sql_builder_pkg.add_select (l_my_query, 'deptno');
sql_builder_pkg.add_from (l_my_query, 'emp');
sql_builder_pkg.add_where (l_my_query, 'ename = :p_ename');
sql_builder_pkg.add_where (l_my_query, 'sal > :p_sal');
l_sql := sql_builder_pkg.get_sql (l_my_query);
dbms_output.put_line (l_sql);
end;
I used it in one project and it was a good tool.

PL/SQL CRUD matrix from a source code

I am trying to create a CRUD matrix for my function from a source code of that function, so I created a procedure that will read a source code.
create or replace procedure test_
IS
CURSOR c_text is
SELECT USER_SOURCE.TEXT
FROM USER_SOURCE
WHERE USER_SOURCE.name='TEST_FUNCTION'
AND USER_SOURCE.type='FUNCTION';
order by line;
v_single_text varchar2(4000);
v_tmp_text varchar2(10000) := ' ';
begin
open c_text;
loop
fetch c_text into v_single_text;
exit when c_text%notfound;
v_tmp_text := v_tmp_text|| chr(10) || rtrim(v_single_text);
dbms_output.put_line(v_single_text);
end loop;
close c_text;
end test_;
And that works very good for me, I get the source code of my desired function. It's a very simple function and I use this to learn PL/SQL. Output of that procedure look's like this.
function test_funkction Return varchar2
IS
kpp_value varchar2(20);
begin
select KPP
into kpp_value
from CUSTOMER
where CUSTOMER_ID = 200713;
dbms_output.put_line (kpp_value);
Return kpp_value;
end test_function;
Now, how to parse the string I've got in the output to get a desired result, my result should be like this
==TABLE_NAME==========OPERATIONS==
CUSTOMER - R - -
==================================
Now I have managed to do it.
But it will only work with my simple function, now I want to make a procedure that will work with any function.
Source code below.
create or replace procedure test_
IS
v_string_fnc varchar2(10000) := UPPER('function test_function
Return varchar2
IS
kpp_value varchar2(20);
begin
select KPP into kpp_value from CUSTOMER where CUSTOMER_ID = 200713;
dbms_output.put_line (kpp_value);
Return kpp_value;
end test_function;');
v_check PLS_INTEGER;
CURSOR c_text is
SELECT USER_SOURCE.TEXT
FROM USER_SOURCE
WHERE USER_SOURCE.name = 'TEST_FUNCTION'
AND USER_SOURCE.type = 'FUNCTION'
order by line;
v_single_text varchar2(4000);
v_tmp_text varchar2(10000) := ' ';
/*v_string varchar2(10000);*/
insert_flag char := '-';
read_flag char := '-';
update_flag char := '-';
delete_flag char := '-';
empty_space char(34) := ' ';
underline char(42) := '==========================================';
/*v_txt varchar2(10000) := ' ';*/
result_table varchar2(1000) := '/';
begin
open c_text;
loop
fetch c_text
into v_single_text;
exit when c_text%notfound;
v_tmp_text := v_tmp_text || chr(10) || rtrim(v_single_text);
/* print source code*/
/*dbms_output.put_line(v_single_text);*/
end loop;
close c_text;
/*DELETE SEARCH*/
v_check := instr(v_string_fnc, 'DELETE ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO DELETE COMMAND');
else
dbms_output.put_line('THERE IS A DELETE COMMAND');
delete_flag := 'D';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY DELETE: ' || result_table);
end if;
/*SELECT SEARCH*/
v_check := instr(v_string_fnc, 'SELECT ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO READ COMMAND');
else
dbms_output.put_line('THERE IS A READ COMMAND');
read_flag := 'R';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY READ: ' || result_table);
end if;
/*UPDATE SEARCH*/
v_check := instr(v_string_fnc, 'UPDATE ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO UPDATE COMMAND');
else
dbms_output.put_line('THERE IS A UPDATE COMMAND');
update_flag := 'U';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY UPDATE: ' || result_table);
end if;
/*INSERT SEARCH*/
v_check := instr(v_string_fnc, 'INSERT ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO CREATE COMMAND');
else
dbms_output.put_line('THERE IS A CREATE COMMAND');
insert_flag := 'C';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY CREATE: ' || result_table);
end if;
dbms_output.put_line(' ');
dbms_output.put_line('==========' || 'TABLE_NAME' || '==========' ||
'OPERATIONS' || '==');
dbms_output.put_line(empty_space || insert_flag || read_flag ||
update_flag || delete_flag);
dbms_output.put_line(underline);
end test_;
With that procedure I can extract and output my code, dbms needs a bit clean up but it will give the result I need.
Now a few questions, how to put a source code of my function to a variable that is not predefined, here is v_string_fnc but it needs to be predefined to work.
And how to link a certain operation with the table, here in my example is easy, one SELECT and keyword FROM that gives me a name of table.
Struggling continues
The bigger part it's done, just a tuning after this.
v_check := instr2(v_string_fnc, 'DROP ');
if v_check > 0 then
delete_flag := 'D';
v_check := instr2(v_string_fnc, 'TABLE ', v_check);
v_check := v_check + 6;
result_table := substr(v_string_fnc, v_check);
rest_string := result_table;
result_table := substr(result_table, 0, instr(result_table, ' '));
result_table := rtrim(result_table);
result_table := rtrim(result_table, ';');
merge into result_set
using dual
on (tables_used = result_table)
when matched then
update set drop_operation = delete_flag
when not matched then
insert
(tables_used, drop_operation)
values
(result_table, delete_flag);
while v_check > 0 loop
v_check := instr2(rest_string, 'DROP ');
if v_check > 0 then
delete_flag := 'D';
v_check := instr2(rest_string, 'TABLE ', v_check);
v_check := v_check + 6;
result_table := substr(rest_string, v_check);
rest_string := result_table;
result_table := substr(result_table, 0, instr(result_table, ' '));
result_table := rtrim(result_table);
result_table := rtrim(result_table, ';');
merge into result_set
using dual
on (tables_used = result_table)
when matched then
update set drop_operation = delete_flag
when not matched then
insert
(tables_used, drop_operation)
values
(result_table, delete_flag);
end if;
end loop;
end if;

Selection of columns in stored procedure based on parameters

I need to check the parameters in the stored procedure if it is entered then I need to select that
i=j=k=l=m=1;
IF (p_plant_cd IS NULL) THEN
i=0;
END IF;
IF(p_global_duns_nbr IS NULL) THEN
j=0
END IF;
IF(p_global_duns_nbr IS NULL) THEN
k=0
END IF;
IF(p_matrl_grp IS NULL) THEN
l=0
END IF;
IF (p_mrp IS NULL) THEN
m=0
END IF ;
Which ever value is 1 I need to add corresponding parameters in the variable v_select
For eg ;
if k and l are 1 then
v_select='p_global_duns_nbr,p_matrl_grp'
Pls suggest me how to do this.
You can declare a variable , holding column names , then concat to select statement and you have SQL select statement in v_select , use it as you want
declare
v_columns varchar2(255);
v_select varchar2(2000);
v_result sys_refcursor;
begin
v_columns := 'rownum';
IF p_plant_cd = 1 THEN
v_columns := v_columns || ',p_plant_cd';
END IF;
IF p_global_duns_nbr = 1 THEN
v_columns := v_columns || ',p_global_duns_nbr';
END IF;
IF p_global_duns_nbr = 1 THEN
v_columns := v_columns || ',p_global_duns_nbr';
END IF;
IF p_matrl_grp = 1 THEN
v_columns := v_columns || ',p_matrl_grp';
END IF;
IF p_mrp = 1 THEN
v_columns := v_columns || ',p_mrp';
END IF;
v_select := 'SELECT ' || v_columns || ' FROM table';
open v_result for v_select;
end;

How to write a FOR EACH loop in PL/SQL?

Is it possible to run a for each loop on a PL/SQL array?
for i in my_array.first ..my_array.last loop
--do_something with my_array(i);
end loop;
It's no possible to iterate over the associative arrays with a non numeric index with a FOR-loop. The solution below works just fine.
-- for-each key in (associative-array) loop ...
declare
type items_type is table of varchar2(32) index by varchar2(32);
items items_type;
begin
items('10') := 'item 10';
items('20') := 'item 20';
items('30') := 'item 30';
dbms_output.put_line('items=' || items.count);
<<for_each>> declare key varchar2(32); begin loop
key := case when key is null then items.first else items.next(key) end;
exit when key is null;
dbms_output.put_line('item(' || key || ')=' || items(key));
--do something with an item
end loop; end for_each;
end;
In my opinion 0xdb solution is best.
Even if you have numeric index it is better to us this construct
DECLARE
TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
--
vt_SomeTable TTab_SomeTable;
vi_Idx NUMBER;
BEGIN
vt_SomeTable(1) := 'First';
vt_SomeTable(2) := 'Second';
vt_SomeTable(5) := 'Fifth';
vt_SomeTable(10) := 'Tenth';
vi_Idx := vt_SomeTable.FIRST;
LOOP
--
EXIT WHEN vi_Idx IS NULL;
--
dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
--
vi_Idx := vt_SomeTable.NEXT(vi_Idx);
--
END LOOP vi_Idx;
END;
It is not susceptible to index discontinuity like below two examples, which will fail on index 3:
DECLARE
TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
--
vt_SomeTable TTab_SomeTable;
BEGIN
vt_SomeTable(1) := 'First';
vt_SomeTable(2) := 'Second';
vt_SomeTable(5) := 'Fifth';
vt_SomeTable(10) := 'Tenth';
-- Throw No_data_found on vi_Idx = 3
FOR vi_Idx IN vt_SomeTable.FIRST .. vt_SomeTable.LAST
LOOP
dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
END LOOP vi_Idx;
END;
DECLARE
TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
--
vt_SomeTable TTab_SomeTable;
BEGIN
vt_SomeTable(1) := 'First';
vt_SomeTable(2) := 'Second';
vt_SomeTable(5) := 'Fifth';
vt_SomeTable(10) := 'Tenth';
-- Throw No_data_found on vi_Idx = 3.
FOR vi_Idx IN 1 .. vt_SomeTable.COUNT
LOOP
dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
END LOOP vi_Idx;
END;