PL/SQL Cursor already open within function? [duplicate] - oracle

I am trying to create a procedure and it created without error. However when I try to run it then I will get following error. Please advise
SQL> begin
2 Update_STUD_Fin ( '1011');
3 end;
4 /
begin
*
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "ORAIN.UPDATE_STUD_FIN", line 3
ORA-06512: at "ORAIN.UPDATE_STUD_FIN", line 8
ORA-06512: at line 2
The Procedure is
SQL> CREATE OR REPLACE PROCEDURE Update_STUD_Fin ( AIDY_CODE IN VARCHAR2 ) IS
2 CURSOR PublicationC IS
3 SELECT SGidm from SGB
4 WHERE SGCODE_EFF ='201030';
5 BEGIN
6 OPEN PublicationC;
7
8 FOR PublicationR IN PublicationC
9 LOOP
10 DBMS_OUTPUT.PUT_LINE( PublicationR.SGidm );
11 END LOOP;
12
13 close PublicationC;
14
15 END;
16 /
Procedure created.

You cannot explicity OPEN the cursor and also use it in an implicit FOR loop. You much choose either implicit (FOR loop) or explicit(OPEN/FETCH/CLOSE).

If you use a cursor with a FOR/IN/LOOP, you don't need to open it explictly. Just write:
SQL> CREATE OR REPLACE PROCEDURE Update_STUD_Fin ( AIDY_CODE IN VARCHAR2 ) IS
2 CURSOR PublicationC IS
3 SELECT SGidm from SGB
4 WHERE SGCODE_EFF ='201030';
5 BEGIN
8 FOR PublicationR IN PublicationC
9 LOOP
10 DBMS_OUTPUT.PUT_LINE( PublicationR.SGidm );
11 END LOOP;
12
15 END;
16 /

6512 Error message indicates the line number in PL-SQL code that the error resulted.
Are you sure you don't have another message before ?

I don't know why you're getting an ORA-06512 message with no other error message above it. Are you sure you have pasted the entire error message?
ORA-06512 is only used when printing out stack traces when an exception is raised in PL/SQL code. Here's a complete example:
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at "USER.SOME_PROCEDURE", line 5
ORA-06512: at line 1
The real error here is the ORA-01001. The ORA-06512s merely state where the error occurred: on line 5 of USER.SOME_PROCEDURE, which was called by line 1 of an anonymous PL/SQL block.
Taking a look at your code, I can spot a couple of problems:
When using FOR ... IN some_cursor LOOP ... then you should not explicitly open and close the cursor. That will be done for you automatically by the FOR loop.
You should also not attempt to close a cursor that hasn't been opened. If you try to do this, you'll get an ORA-01001 'invalid cursor' error message. I'm guessing you've put this in to ensure that the cursor was closed before you opened it, but unfortunately you can't do that.
In short, you should delete all of the OPEN and CLOSE statements from your procedure and try again.

Related

Is no-data-found exception not raised implicitly?

question 1:
I noticed the no-data-found exception not raised implicitly, do we need to raise them manually/explicitly?
Question 2:
I writing a SP package with 4 procedures in it and i'm writing below procedures on a single table.
the exception handling is repetitive in each procedure. is there any guidance/coding standard to keep it in a single place procedure#5 or function and call it there.
Select
Update
Insert
Delete
I guess if I keep it in a function it would raise the exception and return to the called procedure and continue to run ? but when we raise a exception the program should stop , right?
You have run into the only exception in PL/SQL exception handling - ORA-1403: no data found is suppressed when it is generated by a function called in a SQL context.
No data found exceptions work fine in PL/SQL anonymous blocks:
SQL> declare
2 v_number number;
3 begin
4 select 1 into v_number from dual where 1=0;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 4
And no data found also works as expected with a function called in a PL/SQL statement:
SQL> create or replace function exception_no_data_found return number is
2 v_number number;
3 begin
4 select 1 into v_number from dual where 1=0;
5 return v_number;
6 end;
7 /
Function created.
SQL> declare
2 v_number number;
3 begin
4 v_number := exception_no_data_found;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "JHELLER.EXCEPTION_NO_DATA_FOUND", line 4
ORA-06512: at line 4
But when calling the function in a SQL context, the exception disappears:
SQL> select exception_no_data_found from dual;
EXCEPTION_NO_DATA_FOUND
-----------------------
I think the reason for this is that SQL internally uses the no data found exception to let the system know there are no more rows, so it's not always an exception. (This behavior is probably a bug but has been around for so long that it'll never change.)
To raise that exception in this situation, you must manually catch and raise a different exception like this:
SQL> create or replace function exception_no_data_found return number is
2 v_number number;
3 begin
4 select 1 into v_number from dual where 1=0;
5 return v_number;
6 exception when no_data_found then
7 raise_application_error(-20000, 'No data found.');
8 end;
9 /
Function created.
SQL> select exception_no_data_found from dual;
select exception_no_data_found from dual
*
ERROR at line 1:
ORA-20000: No data found.
ORA-06512: at "JHELLER.EXCEPTION_NO_DATA_FOUND", line 7
But the above situation is by far the weirdest part about Oracle exception handling. Other than this scenario, in general you are almost always better off by not doing any exception handling. Just let the program break; the exceptions will propagate up, and the application will get an exception that includes the full error message and the exact line number of the error. In practice, that information is almost always enough to debug any problems. Only add custom exception handling when you know for sure that you need to gather extra data.

How to rollback and exit in sqlplus whenever SQL WARNINGS occurs in Oracle PL/SQL? [duplicate]

I am deploying pl/sql code using several sql files that are called with ##file. If a package got a compilation error the script continues to the end.
Is there a way to stop on every compilation error?
I tried WHENEVER SQLERROR EXIT SQL.SQLCODE but the script still continues.
No native sql*plus way I'm aware of. Only workarounds. Like this:
20:42:50 TEST#oars_sandbox> get scr
1 whenever sqlerror exit rollback
2 create or replace procedure my_failed_proc as
3 i number;
4 begin
5 select 1 into i from me_iz_not_exist;
6 end;
7 /
8 #check my_failed_proc
9 create or replace procedure my_correct_proc as
10 i number;
11 begin
12 select 1 into i from dual;
13 end;
14 /
15* #check my_correct_proc
20:42:57 16 .
20:42:59 TEST#oars_sandbox> get check
1 declare
2 l_status varchar2(100);
3 begin
4 select status into l_status
5 from all_objects where object_name = upper('&1');
6 if l_status = 'INVALID' then
7 raise_application_error(-20000, 'Object &1 is invalid!');
8 end if;
9* end;
20:43:02 10 .
20:43:04 TEST#oars_sandbox> #scr
Warning: Procedure created with compilation errors.
Elapsed: 00:00:00.05
declare
*
ERROR at line 1:
ORA-20000: Object my_failed_proc is invalid!
ORA-06512: at line 8
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production

halt on compilation error in a sqlplus script

I am deploying pl/sql code using several sql files that are called with ##file. If a package got a compilation error the script continues to the end.
Is there a way to stop on every compilation error?
I tried WHENEVER SQLERROR EXIT SQL.SQLCODE but the script still continues.
No native sql*plus way I'm aware of. Only workarounds. Like this:
20:42:50 TEST#oars_sandbox> get scr
1 whenever sqlerror exit rollback
2 create or replace procedure my_failed_proc as
3 i number;
4 begin
5 select 1 into i from me_iz_not_exist;
6 end;
7 /
8 #check my_failed_proc
9 create or replace procedure my_correct_proc as
10 i number;
11 begin
12 select 1 into i from dual;
13 end;
14 /
15* #check my_correct_proc
20:42:57 16 .
20:42:59 TEST#oars_sandbox> get check
1 declare
2 l_status varchar2(100);
3 begin
4 select status into l_status
5 from all_objects where object_name = upper('&1');
6 if l_status = 'INVALID' then
7 raise_application_error(-20000, 'Object &1 is invalid!');
8 end if;
9* end;
20:43:02 10 .
20:43:04 TEST#oars_sandbox> #scr
Warning: Procedure created with compilation errors.
Elapsed: 00:00:00.05
declare
*
ERROR at line 1:
ORA-20000: Object my_failed_proc is invalid!
ORA-06512: at line 8
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production

How can I get the procedure/function name where an exception occurs, in PLSQL?

How can I get a procedure/function name where an exception occurs in PLSQL?
I need this to create a log of the procedures that have problems in a package.
Unfortunately there is no way to get a stored procedure name, that is wrapped in a package, at run time. Any method, whether it $$PLSQL_UNIT inquiry directive or FORMAT_ERROR_BACKTRACE function of dbms_utility package, that allows you to do that in a case of a stand-alone stored procedure will always give you the anonymous block instead of a name in a case of a stored procedure that is wrapped in the package. Hence your only choice is to capture a package name and the line number on which an error has occurred by using dbms_utility.format_error_backtrace for example.
SQL> create or replace package some_pkg
2 as
3 procedure some_proc;
4 end;
5 /
Package created
SQL>
SQL> create or replace package body some_pkg
2 as
3 procedure Some_Proc
4 is
5 l_var number;
6 begin
7 l_var := 1/0;
8 exception
9 when others
10 then dbms_output.put_line(dbms_utility.format_error_backtrace);
11 end;
12 end;
13 /
Package body created
SQL> exec some_pkg.some_proc;
ORA-06512: at "HR.SOME_PKG", line 7
Did u mean get all procedures that has 'exception' in their source ?
if so then :
select distinct t.name from user_source t
where upper(t.text) like '%EXCEPTION%' or
upper(t.text) like '%RAISE_APPLICATION_ERROR%';
I hope it helps you :)

CREATE Oracle Procedure

I am trying to create a procedure and it created without error. However when I try to run it then I will get following error. Please advise
SQL> begin
2 Update_STUD_Fin ( '1011');
3 end;
4 /
begin
*
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "ORAIN.UPDATE_STUD_FIN", line 3
ORA-06512: at "ORAIN.UPDATE_STUD_FIN", line 8
ORA-06512: at line 2
The Procedure is
SQL> CREATE OR REPLACE PROCEDURE Update_STUD_Fin ( AIDY_CODE IN VARCHAR2 ) IS
2 CURSOR PublicationC IS
3 SELECT SGidm from SGB
4 WHERE SGCODE_EFF ='201030';
5 BEGIN
6 OPEN PublicationC;
7
8 FOR PublicationR IN PublicationC
9 LOOP
10 DBMS_OUTPUT.PUT_LINE( PublicationR.SGidm );
11 END LOOP;
12
13 close PublicationC;
14
15 END;
16 /
Procedure created.
You cannot explicity OPEN the cursor and also use it in an implicit FOR loop. You much choose either implicit (FOR loop) or explicit(OPEN/FETCH/CLOSE).
If you use a cursor with a FOR/IN/LOOP, you don't need to open it explictly. Just write:
SQL> CREATE OR REPLACE PROCEDURE Update_STUD_Fin ( AIDY_CODE IN VARCHAR2 ) IS
2 CURSOR PublicationC IS
3 SELECT SGidm from SGB
4 WHERE SGCODE_EFF ='201030';
5 BEGIN
8 FOR PublicationR IN PublicationC
9 LOOP
10 DBMS_OUTPUT.PUT_LINE( PublicationR.SGidm );
11 END LOOP;
12
15 END;
16 /
6512 Error message indicates the line number in PL-SQL code that the error resulted.
Are you sure you don't have another message before ?
I don't know why you're getting an ORA-06512 message with no other error message above it. Are you sure you have pasted the entire error message?
ORA-06512 is only used when printing out stack traces when an exception is raised in PL/SQL code. Here's a complete example:
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at "USER.SOME_PROCEDURE", line 5
ORA-06512: at line 1
The real error here is the ORA-01001. The ORA-06512s merely state where the error occurred: on line 5 of USER.SOME_PROCEDURE, which was called by line 1 of an anonymous PL/SQL block.
Taking a look at your code, I can spot a couple of problems:
When using FOR ... IN some_cursor LOOP ... then you should not explicitly open and close the cursor. That will be done for you automatically by the FOR loop.
You should also not attempt to close a cursor that hasn't been opened. If you try to do this, you'll get an ORA-01001 'invalid cursor' error message. I'm guessing you've put this in to ensure that the cursor was closed before you opened it, but unfortunately you can't do that.
In short, you should delete all of the OPEN and CLOSE statements from your procedure and try again.

Resources