NO_DATA_FOUND exception handling with Select Into MULTIPLE variables - sql

I have looked for a while now for a solution to this issue, and all the NO_DATA_FOUND handling tutorials I found only show how to do it when doing a Select Into with only one column into one variable.
First, here is my code:
BEGIN
OPEN c_no_source;
LOOP
DECLARE
l_price_code VARCHAR2(20) := '';
l_price_level VARCHAR(10) := '';
l_code_date DATE := p_effective_date;
BEGIN
FETCH c_no_source INTO c_no_source_row;
exit WHEN c_no_source%NOTFOUND;
BEGIN
WITH codeList AS /* liste des dates ayant une donnée avant la date effective incluse. */
(
SELECT distinct
NVL(effective_date,p_effective_date) as effective_date,
NVL(user_group2,'') as price_code,
NVL(user_group3,'') as price_level
FROM DGA_Service.Hjvsecmaster_Hist
WHERE effective_date <= p_effective_date
AND user_group2 IS NOT NULL
AND security_alias = c_no_source_row.security_alias
ORDER BY 1 DESC
)
SELECT price_code, price_level, effective_date
INTO l_price_code, l_price_level, l_code_date
FROM codelist
WHERE ROWNUM = 1;
EXCEPTION WHEN no_data_found THEN NULL;
...
[UPDATE statement using the variables]
...
END;
END;
END LOOP;
CLOSE c_no_source;
END;
What I'm trying to do is take the top 1 result of my codeList temp result set into three separate variables.
However one of the three columns in codeList will often be NULL. And none of my 3 variables will be set.
I tried to handle the exception but I can't get my code to insert the columns that DO have a value into their respective variables. If even one of the columns is NULL then none of them are inserted into their variable.
I would like the Select Into statement to set the variables that it CAN set.
I tried to handle them all separately using something like this:
EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;
But I got the following error message:
ORA-06550: line 294, column 18:
PLS-00201: identifier 'PRICE_CODE' must be declared
ORA-06550: line 294, column 15:
PL/SQL: Statement ignored
ORA-06550: line 295, column 18:
PLS-00201: identifier 'PRICE_LEVEL' must be declared
ORA-06550: line 295, column 15:
PL/SQL: Statement ignored
ORA-06550: line 296, column 18:
PLS-00201: identifier 'EFFECTIVE_DATE' must be declared
ORA-06550: line 296, column 15:
PL/SQL: Statement ignored
So I ran out of ideas. I tried specifying the temp table name, to no avail, like this:
IF codeList.price_code IS NOT NULL
I would love any help on this issue. The package this piece of code runs in is already heavy and I would prefer not to have to get each column with a separate With ... As () Select Into clause.

Okay, I think I get you; most of your problem is caused by you nesting PL/SQL blocks incorrectly.
Your update statement is contained within the EXCEPTION block, which means it'll only get executed if the exception is thrown. Secondly, you're referencing the columns directly in the following:
EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;
This is the cause of your compilation error.
Lastly, if there is a single row in your select into then every variable will be set, so there's no need to try to deal with this.
BEGIN
OPEN c_no_source;
LOOP
DECLARE
l_price_code VARCHAR2(20);
l_price_level VARCHAR(10);
l_code_date DATE := p_effective_date;
BEGIN
FETCH c_no_source INTO c_no_source_row;
exit WHEN c_no_source%NOTFOUND;
BEGIN
WITH codelist AS (
SELECT DISTINCT effective_date
, user_group2 AS price_code
, user_group3 AS price_level
FROM hjvsecmaster_hist
WHERE effective_date <= p_effective_date
AND user_group2 IS NOT NULL
AND security_alias = c_no_source_row.security_alias
ORDER BY 1 DESC
)
SELECT price_code, price_level, effective_date
INTO l_price_code, l_price_level, l_code_date
FROM codelist
WHERE ROWNUM = 1;
EXCEPTION WHEN no_data_found THEN
-- All variables are their initial setting
null;
END;
...
[UPDATE statement using the variables]
...
END;
END LOOP;
CLOSE c_no_source;
END;
This is normally a highly inefficient way of doing this. If you can fit everything into a single UPDATE or MERGE then I would do so. You don't appear to have any additional logic so it should be possible.

However one of the three will often be NULL, and trigger the
NO_DATA_FOUND error, and none of my 3 variables will be set
NO_DATA_FOUND is raised when the query does not return any rows. It has nothing to do with the column values. They could all be null and the statement would succeed.
EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;
your variables are prefixed with "l_" and you are using the column names eg.price_code in your comparision, hence the error. More importantly, NO_DATA_FOUND would mean all the variable values are null, so this exception block does not do anything.
All you'd probably need is this.
if you don't want to insert null values for a given id (if all are null)
BEGIN
insert into target_table (id, col1, col2, col3)
select id, col1, col2, col3
from (target_table)
where not (col1 is null and col2 is null and col3 is null);
commit;
end;
/
If there is no data for a given id, nothing is inserted. If atleast one of them is not null, then these values are inserted.

Related

How can I handle this compilation error through exception?

How can I handle this compilation error through exception?
declare
table_or_view_does_not_exist exception;
pragma exception_init(table_or_view_does_not_exist,-00942);
b exception;
pragma exception_init(b,-00942);
d_table varchar2(200);
c_table varchar2(200);
c_count Number;
begin
begin
d_table:='drop table audit_table PURGE';
execute immediate d_table;
exception
when table_or_view_does_not_exist then
null;
end;
<<lable>>
c_table := 'create table audit_table
(table_name varchar2(50),
column_name varchar2(50),
count_type varchar2(50),
v_count number)';
execute immediate c_table;
select count(*) into c_count from customer_profile where cust_id is null;
insert into audit_table columns (table_name,column_name,count_type,v_count) values('customer_profile','cust_id','null','c_count');
exception
when b then
GOTO lable;
end;
Error report:
ORA-06550: line 25, column 13:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 25, column 1:
PL/SQL: SQL Statement ignored
ORA-06550: line 28, column 2:
PLS-00375: illegal GOTO statement; this GOTO cannot branch to label 'LABLE'
ORA-06550: line 28, column 2:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
What you do, is just bad practice. In Oracle, we don't create tables in PL/SQL but at SQL level and then use them in our procedures.
In your case, you'd
-- create table first
create table audit_table ...;
-- use it in PL/SQL procedure
declare
...
begin
...
insert into audit_table ...
end;
/
You can't "handle" compilation error through exception. What you could do is to put insert statement into dynamic SQL. Also, it wouldn't harm if you used valid syntax (there's no columns "keyword" there).
execute immediate q'[insert into audit_table
(table_name, column_name, count_type, v_count)
values('customer_profile', 'cust_id', 'null', :a)]'
using c_count;
but - once again - that's just bad practice. Don't do it that way, there's no benefit and many disadvantages.
As of goto - well, jumping around your code is almost always wrong. Error you got says that you can't jump out of the exception handler so your idea was wrong anyway.
You actually can trap compilation errors, by wrapping the whole block in an execute immediate so compilation is postponed until runtime. But that's not the right way to go.
Your real issue is that you are referring to the object you are dynamically dropping/creating as a hard-coded dependency of your PL/SQL block:
insert into audit_table ... -- this is a hard dependency
You can't compile PL/SQL if hard dependencies don't exist until run time. If you really must dynamically drop/recreate the table (and I agree with the above reviewer that this is architecturally questionable), you must also make this insert dynamic as well in order to break the dependency chain:
execute immediate 'insert into audit_table values (:col1, :col2, :col3, :col4)' using 'customer_profile','cust_id','null','c_count'; -- this creates no dependency
That will prevent Oracle from creating an object dependency on this table so your code can compile even though the table does not exist at compile time.
But once again, please be sure this is the right technique. There are only a few rare cases where this actually makes good architectural sense. Oh, and please remove the GOTO and label junk. We really don't use that in modern languages; they create unmanageable spaghetti code.
Could you consider another way to control the flow - comments in the code:
DECLARE
cmd VarChar2(200);
c_count Number(6);
--
Status VarChar2(255);
BEGIN
cmd :='drop table audit_table';
Begin -- 1st nested PL/SQL block
Execute Immediate cmd;
Status := 'OK';
Exception -- this could be raised if the table doesn't exist which is probably OK
When OTHERS Then
Status := 'OK'; -- SQLERRM = ORA-00942: table or view does not exist - nothing happens - it would be droped anyway
-- Status := 'ERR - ' || SQLERRM; -- this is alternative if you want to do something else with this ERR
End;
If Status != 'OK' Then -- here you can check the status and decide what to do
GoTo EndIt;
End If;
--
<<lable>> -- in this code there is no need for this label
cmd := 'create table audit_table (table_name varchar2(50), column_name varchar2(50), count_type varchar2(50), v_count number)';
Begin -- 2nd nested PL/SQL block
Execute Immediate cmd;
Status := 'OK';
Exception
When OTHERS Then
Status := 'ERR - ' || SQLERRM;
End;
If Status != 'OK' Then -- here you can check the status and decide what to do
dbms_output.putline(Status); -- send error message and exit - there is no audit_table
GoTo EndIt;
Else
Null; -- here you can do something else (if maybe the table already exists)
End If;
--
-- think about what could go wrong below (2 lines) and either leave it as it is or put it in the 3rd nested PL/SQL block
Select count(*) Into c_count From customer_profile Where cust_id Is Null;
insert into audit_table (table_name, column_name, count_type, v_count) values('customer_profile', 'cust_id', 'Null', c_count);
<<EndIt>> -- used to end the block if needed
Null;
EXCEPTION
When OTHERS Then
dbms_output.putline(SQLERRM); -- You can not get out of here since it is main PL/SQL blok that went into an exception
END;
Addition
Below is an option of basic steps to do the job (3rd block) without compilation errors. I have no possibility to check it out so please do it yourself (there could be some syntax problem or something else). The goal is to be sure that you can insert the record...
I declared sq variable to construct insert command and the end of the code above could be (please check the command yourself - I can't test it right now) something like here:
DECLARE
...
sq VarChar2(1) := ''''; -- this is single-quote character
...
BEGIN
...
...
--
-- think about what could go wrong below (2 lines) and either leave it as it is or put it in the 3rd nested PL/SQL block
Select count(*) Into c_count From customer_profile Where cust_id Is Null;
cmd := 'insert into audit_table (table_name, column_name, count_type, v_count) values(' || sq || 'customer_profile' || sq || ', ' || sq || 'cust_id' || sq || ', ' || sq || 'Null' || sq || ', ' || c_count || ')';
Begin -- 3rd nested PL/SQL block
Select Count(*) Into c_count From all_tables Where table_name = 'audit_table' and owner = 'your_table_owner'; -- check if table exist - if it doesn't set Status
If c_count = 1 Then -- if table exists then you can insert the record
Execute Immediate cmd;
Status := 'OK'; -- all done
Else
Status := 'ERR';
End If;
Exception
When OTHERS Then
Status := 'ERR - ' || SQLERRM; -- catch error and pass it to the main block
End;
If Status != 'OK' Then -- here you can check the status and decide what to do
dbms_output.putline(Status); -- send error message and exit - there is no audit_table -->> OR DO SOMETHING ELSE
GoTo EndIt;
Else
Null; -- here you can do something else if you wish
End If;
--
<<EndIt>> -- used to end the block if needed
Null;
EXCEPTION
When OTHERS Then
dbms_output.putline(SQLERRM); -- You can not get out of here since it is main PL/SQL blok that went into an exception
END;

Raise exception in stored procedure based on view entries

I have a stored procedure. I would like to implement the below logic, which I have written in pseudocode.
If the below query has one of more entries:
SELECT
NULL
FROM
table1
WHERE
condition
GROUP BY
column
HAVING
COUNT(1) > 1
UNION ALL
SELECT
NULL
FROM
table1 a
WHERE
condition
AND EXISTS (
SELECT
NULL
FROM
table2 b
WHERE
condition
);
Then raise an exception and stop the stored procedure.
Here is an example of raising an exception if a particular value is found from a query:
declare
somevar dual.dummy%type;
begin
select 'Y' into somevar
from dual;
if somevar = 'Y' then
raise_application_error(-20123, 'Hull breach on deck 15. Abandon ship.');
end if;
end;
The "select from dual" can be any query, so feel free to substitute your unions and counts (though we should really stick to the standard count(*), not count('Dracula') etc).
Let's do this with the sample emp/dept schema - just plug in your own statement for your use case. You do need to declare since in pl/sql you cannot "just select". You always need to select into a variable. I usually just select the number 1 into a dummy variable of type number. The trick is to raise the exception after the SELECT INTO and do nothing on NO_DATA_FOUND.
You can use named exceptions to distinguish different cases but since a no data found will throw an exception you have to do each of the cases in its own block. The cleanest is to handle all named exceptions in the final exception block.
DECLARE
l_dummy NUMBER;
king_exists EXCEPTION;
dave_exists EXCEPTION;
BEGIN
BEGIN
SELECT 1 INTO l_dummy FROM emp WHERE ename = 'DAVE';
RAISE dave_exists;
EXCEPTION WHEN NO_DATA_FOUND THEN
NULL;
END;
BEGIN
SELECT 1 INTO l_dummy FROM emp WHERE ename = 'KING';
RAISE king_exists;
EXCEPTION WHEN NO_DATA_FOUND THEN
NULL;
END;
EXCEPTION
WHEN dave_exists THEN
raise_application_error(-20000,'My expection error message');
WHEN king_exists THEN
raise_application_error(-20001,'King exists');
END;
/

How to get NULL condition checks for PL/SQL associative array DS

I have the following code snippet and I would like to know how to check for existence of an entry in the associative array
set serveroutput on;
DECLARE
TYPE per_form_metric IS record
(
output_achieved_itd NUMBER,
output_achieved_ptd NUMBER
);
TYPE per_form_metrics_tbl IS TABLE OF per_form_metric INDEX BY VARCHAR2(10) ;
TYPE interval_number_tbl IS TABLE OF per_form_metrics_tbl INDEX BY VARCHAR2(10) ;
TYPE ms_output_tbl IS TABLE OF interval_number_tbl INDEX BY VARCHAR2(100) ;
g_ms_output_tbl ms_output_tbl ;
l_per_f_rec per_form_metric;
l_per_f_tbl per_form_metrics_tbl;
l_per_int_tbl interval_number_tbl;
l_ms_out_tbl ms_output_tbl;
BEGIN
l_per_f_rec.output_achieved_itd := 1000;
l_per_f_rec.output_achieved_ptd := 1000;
l_per_f_tbl('Period 1') := l_per_f_rec;
l_per_int_tbl('Interval 1') := l_per_f_tbl;
l_ms_out_tbl('1') := l_per_int_tbl;
-- Now get me the output_achieved_itd for 1 , Interval 1, Period 1
dbms_output.put_line(l_ms_out_tbl('1')('Interval 1')('Period 1').output_achieved_itd);
dbms_output.put_line(l_ms_out_tbl('2')('Interval 1')('Period 1').output_achieved_itd);
END;
The output for this code is as below
Error report:
ORA-01403: no data found
ORA-06512: at line 31
01403. 00000 - "no data found"
*Cause:
*Action:
1000
How can I check if
l_ms_out_tbl('2')('Interval 1')('Period 1').output_achieved_itd
exists?
I would like to say something like
IF (l_ms_out_tbl('2')('Interval 1')('Period 1').output_achieved_itd IS NOT NULL) THEN
do something awesome
ELSE
continue wallowing
END IF;
Instead of evaluating for nullality, evaluate for existence:
IF (l_ms_out_tbl.EXISTS('2'))
THEN
IF (l_ms_out_tbl('2').EXISTS('Interval 1'))
THEN
IF (l_ms_out_tbl('2')('Interval 1').EXISTS('Period 1'))
THEN
null; --do something awesome
END IF;
END IF;
ELSE
null; --continue wallowing
END IF;
or catch NO_DATA_FOUND:
begin
dbms_output.put_line(l_ms_out_tbl('2')('Interval 1')('Period 1').output_achieved_itd)
-- did something awesome
exception
when NO_DATA_FOUND then
null;
-- continue wallowing
end;
Use exists collection method. E.g.:
declare
type foo_t is table of varchar2(20) index by varchar2(20);
v_foos foo_t;
begin
v_foos('FOO') := 'this is foo';
if v_foos.exists('FOO') then
dbms_output.put_line('exists');
else
dbms_output.put_line('not exists');
end if;
end;
/
How to apply that to nested associative arrays is left to the OP :)
See also:
PL/SQL - Working with a string!
Why is this check for null associative array in PL/SQL failing?

Error in plsql . here flag has value 1 or no data. when no data i have to insert somethings but error coming.suggestions please

CREATE OR REPLACE PACKAGE BODY BAS_NUMB_UPD AS
PROCEDURE BAS_NUM_UPDN AS
CURSOR cur IS
SELECT DISTINCT o.obj_id,LTRIM(substr(convert_171_to_711(cp.T_C_CP),1,7),'0') bas_n
FROM t_obj o, mat_tea_rel mpr, coorg_tea cp
WHERE o.obj_type = 'Resin'
AND o.obj_id = mpr.obj_id
AND mpr.p_k_id = cp.p_k_id;
l_b_num_attr_id number(10) := get_attribute_id('Ba Nu');
flag1 VARCHAR2(10);
BEGIN
FOR x IN cur LOOP
dbms_output.put_line(x.obj_id||'contains b n'||x.bas_n);
SELECT flag INTO flag1
FROM t_xc_s_values
WHERE attr_id = l_b_num_attr_id
AND Obj_id = x.obj_id
AND VALUE = x.bas_n;
EXCEPTION
WHEN NO_DATA_FOUND THEN
flag1 :='Nothing';
WHEN OTHERS THEN
raise_application_error(-20011,'Unknown Exception in PROCEDURE');
END;
IF flag1 = 1 THEN
dbms_output.put_line('flag equal to one');
ELSE
INSERT INTO t_xc_s_values (obj_id, at_id, VALUE,)
VALUES (x.obj_id, l_b_num_attr_id, x.bas_n);
END IF;
END LOOP;
END;
END BAS_NUM_UPDN;
END BAS_NUMB_UPD;
These are the errors
Error(28,1): PLS-00103: Encountered the symbol "EXCEPTION" when
expecting one of the following: begin case declare end exit for
goto if loop mod null pragma raise return select update while with
<< close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe
Error(35,1): PLS-00103: Encountered the symbol "IF" when expecting one
of the following: end not pragma final instantiable order
overriding static member constructor map
Error(47,3): PLS-00103: Encountered the symbol "END" when expecting
one of the following: ;
Your code is not properly nested:
If you have an EXCEPTION part, you need to have the triple BEGIN / EXCEPTION / END on the same level. So you probably need to insert a BEGIN after LOOP.
Each END must match a BEGIN. Besides the missing BEGIN mention before, you have too many END statements at the end. Remove the one on the third last line.
These are just syntactical errors. I didn't check whether the procedure does what you intend.
The errors you get are quite straightforward. You have an EXCEPTION ... END but no matching BEGIN. You want to trap the no_data_found for your flag select, so start that block with a BEGIN
(Why would you use a WHEN OTHERS? Why would you trap it and then say it is 'Unknown'? The error is never unknown.)
BEGIN
FOR x IN cur LOOP
dbms_output.put_line(x.obj_id||'contains b n'||x.bas_n);
BEGIN -- added here
SELECT flag INTO flag1
FROM t_xc_s_values
WHERE attr_id = l_b_num_attr_id
AND Obj_id = x.obj_id
AND VALUE = x.bas_n;
EXCEPTION
WHEN NO_DATA_FOUND THEN
flag1 :='Nothing';
WHEN OTHERS THEN
raise_application_error(-20011,'Unknown Exception in PROCEDURE');
END;
Next error:
your insert statement has one comma too many:
INSERT INTO t_xc_s_values (obj_id, at_id, VALUE,)
Next error:
one END too many
END LOOP;
END; -- this will END your procedure block
END BAS_NUM_UPDN; -- this will complain it has to match the procedure begin
Your PLSQL code is also unnecessary. You could write your logic as a SQL statement, improving your performance.
PROCEDURE BAS_NUM_UPDN AS
IS
l_b_num_attr_id number(10) := get_attribute_id('Ba Nu');
BEGIN
INSERT INTO t_xc_s_values (obj_id, at_id, VALUE)
SELECT DISTINCT o.obj_id,
l_b_num_attr_id,
LTRIM(substr(convert_171_to_711(cp.T_C_CP),1,7),'0') bas_n
FROM t_obj o, mat_tea_rel mpr, coorg_tea cp
WHERE o.obj_type = 'Resin'
AND o.obj_id = mpr.obj_id
AND mpr.p_k_id = cp.p_k_id;
AND NOT EXISTS (SELECT flag
FROM t_xc_s_values
WHERE attr_id = l_b_num_attr_id
AND Obj_id = o.obj_id
AND VALUE = LTRIM(substr(convert_171_to_711(cp.T_C_CP),1,7),'0'));
END;

PL/SQL block problem: No data found error

SET SERVEROUTPUT ON
DECLARE
v_student_id NUMBER := &sv_student_id;
v_section_id NUMBER := 89;
v_final_grade NUMBER;
v_letter_grade CHAR(1);
BEGIN
SELECT final_grade
INTO v_final_grade
FROM enrollment
WHERE student_id = v_student_id
AND section_id = v_section_id;
CASE -- outer CASE
WHEN v_final_grade IS NULL THEN
DBMS_OUTPUT.PUT_LINE ('There is no final grade.');
ELSE
CASE -- inner CASE
WHEN v_final_grade >= 90 THEN v_letter_grade := 'A';
WHEN v_final_grade >= 80 THEN v_letter_grade := 'B';
WHEN v_final_grade >= 70 THEN v_letter_grade := 'C';
WHEN v_final_grade >= 60 THEN v_letter_grade := 'D';
ELSE v_letter_grade := 'F';
END CASE;
-- control resumes here after inner CASE terminates
DBMS_OUTPUT.PUT_LINE ('Letter grade is: '||v_letter_grade);
END CASE;
-- control resumes here after outer CASE terminates
END;
the above code I have taken from the book "Oracle PL/SQL by Example, 4th Edition 2009" my problem is when I enter a student_id not present in the table it returns me the following error
Error report: ORA-01403: no data found
ORA-06512: at line 7
01403. 00000 - "no data found"
*Cause:
*Action:
but according to the book it should have returned a null value and then follow the case flow.
When you are selecting INTO a variable and there are no records returned you should get a NO DATA FOUND error. I believe the correct way to write the above code would be to wrap the SELECT statement with it's own BEGIN/EXCEPTION/END block. Example:
...
v_final_grade NUMBER;
v_letter_grade CHAR(1);
BEGIN
BEGIN
SELECT final_grade
INTO v_final_grade
FROM enrollment
WHERE student_id = v_student_id
AND section_id = v_section_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_final_grade := NULL;
END;
CASE -- outer CASE
WHEN v_final_grade IS NULL THEN
...
There is an alternative approach I used when I couldn't rely on the EXCEPTION block at the bottom of my procedure. I had variables declared at the beginning:
my_value VARCHAR := 'default';
number_rows NUMBER := 0;
.
.
.
SELECT count(*) FROM TABLE INTO number_rows (etc.)
IF number_rows > 0 -- Then obtain my_value with a query or constant, etc.
END IF;
Might be worth checking online for the errata section for your book.
There's an example of handling this exception here http://www.dba-oracle.com/sf_ora_01403_no_data_found.htm
Your SELECT statement isn't finding the data you're looking for. That is, there is no record in the ENROLLMENT table with the given STUDENT_ID and SECTION_ID. You may want to try putting some DBMS_OUTPUT.PUT_LINE statements before you run the query, printing the values of v_student_id and v_section_id. They may not be containing what you expect them to contain.
This data not found causes because of some datatype we are using .
like select empid into v_test
above empid and v_test has to be number type , then only the data will be stored .
So keep track of the data type , when getting this error , may be this will help