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

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

Related

ORA-00900: invalid SQL statement- when run a package in oracle 12c

I am using Oracle 12c database and trying to run a package using SQL commands.
CREATE OR REPLACE PACKAGE "PK_CP_OTM" as
FUNCTION F_CP_OPTIMIZATION (
v_current_day IN VARCHAR2,
v_branch_code IN VARCHAR2)
RETURN VARCHAR2;
END PK_CP_OTM;
When I try to execute it using:
DECLARE
BEGIN
EXECUTE IMMEDIATE PK_CP_OTM.F_CP_OPTIMIZATION('20190409','BRNCD001');
END;
It shows:
ORA-00900: invalid SQL statement
ORA-06512: at line 3
00900. 00000 - "invalid SQL statement"
Thanks for your help.
As #Littlefoot said, you don't need dynamic SQL here, you can make a static call; but as you are calling a function you do need somewhere to put the result of the call:
declare
l_result varchar2(30); -- make it a suitable size
begin
l_result := pk_cp_otm.f_cp_optimization('20190409','BRNCD001');
end;
/
In SQL*Plus, SQL Developer and SQLcl you can use the execute client command (which might have caused some confusion) and a bind variable for the result:
var result varchar2(30);
exec :result := pk_cp_otm.f_cp_optimization('20190409','BRNCD001');
print result
There's nothing dynamic here, so - why would you use dynamic SQL at all?
Anyway: if you insist, then you'll have to select the function into something (e.g. a local variable). Here's an example
First, the package:
SQL> set serveroutput on
SQL>
SQL> create or replace package pk_cp_otm
2 as
3 function f_cp_optimization (v_current_day in varchar2,
4 v_branch_code in varchar2)
5 return varchar2;
6 end pk_cp_otm;
7 /
Package created.
SQL> create or replace package body pk_cp_otm
2 as
3 function f_cp_optimization (v_current_day in varchar2,
4 v_branch_code in varchar2)
5 return varchar2
6 is
7 begin
8 return 'Littlefoot';
9 end;
10 end pk_cp_otm;
11 /
Package body created.
How to call the function?
SQL> declare
2 l_result varchar2 (20);
3 begin
4 execute immediate
5 'select pk_cp_otm.f_cp_optimization (''1'', ''2'') from dual'
6 into l_result;
7
8 dbms_output.put_line ('result = ' || l_result);
9 end;
10 /
result = Littlefoot
PL/SQL procedure successfully completed.
SQL>

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

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.

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

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.

How can we define output parameter size in stored procedure?

How can we define output parameter size in stored procedure?
You can't. Of course, you are in control of how much data you put into the OUT parameter in the stored procedure. If you want you can create a sized local variable to hold the data and then assign the value of that variable to the OUT parameter.
The calling program determines the size of the variable that receives the OUT parameter.
Here is a simple package which declares and uses a subtype:
SQL> create or replace package my_pkg as
2 subtype limited_string is varchar2(10);
3 procedure pad_string (p_in_str varchar
4 , p_length number
5 , p_out_str out limited_string);
6 end my_pkg;
7 /
Package created.
SQL> create or replace package body my_pkg as
2 procedure pad_string
3 (p_in_str varchar
4 , p_length number
5 , p_out_str out limited_string)
6 as
7 begin
8 p_out_str := rpad(p_in_str, p_length, 'A');
9 end pad_string;
10 end my_pkg;
11 /
Package body created.
SQL>
However, if we call PAD_STRING() in such a way that the output string exceeds the subtype's precision it still completes successfully. Bother!
SQL> var out_str varchar2(128)
SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)
PL/SQL procedure successfully completed.
SQL>
SQL> select length(:out_str) from dual
2 /
LENGTH(:OUT_STR)
----------------
12
SQL>
This is annoying but it's the way PL/SQL works so we have to live with it.
The way to resolve the situaton is basically to apply DBC principles and validate our parameters. So, we can assert business rules against the inputs like this:
SQL> create or replace package body my_pkg as
2 procedure pad_string
3 (p_in_str varchar
4 , p_length number
5 , p_out_str out limited_string)
6 as
7 begin
8 if length(p_in_str) + p_length > 10 then
9 raise_application_error(
10 -20000
11 , 'Returned string cannot be longer than 10 characters!');
12 end if;
13 p_out_str := rpad(p_in_str, p_length, 'A');
14 end pad_string;
15 end my_pkg;
16 /
Package body created.
SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)
BEGIN my_pkg.pad_string('PAD THIS!', 12, :out_str); END;
*
ERROR at line 1:
ORA-20000: Returned string cannot be longer than 10 characters!
ORA-06512: at "APC.MY_PKG", line 9
ORA-06512: at line 1
SQL>
Or we can assert business rules against the output like this:
SQL> create or replace package body my_pkg as
2 procedure pad_string
3 (p_in_str varchar
4 , p_length number
5 , p_out_str out limited_string)
6 as
7 l_str limited_string;
8 begin
9 l_str := rpad(p_in_str, p_length, 'A');
10 p_out_str := l_str;
11 end pad_string;
12 end my_pkg;
13 /
Package body created.
SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)
BEGIN my_pkg.pad_string('PAD THIS!', 12, :out_str); END;
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "APC.MY_PKG", line 9
ORA-06512: at line 1
SQL>
In most scenarios we should do both. This is the polite way to build interfaces, because it means other routines can call our procedures with the confidence that they will return the values they say they will.
You could use a subtype in a package header and type check that in the body...
CREATE OR REPLACE PACKAGE my_test
AS
SUBTYPE my_out IS VARCHAR2( 10 );
PROCEDURE do_something( pv_variable IN OUT my_out );
END;
/
CREATE OR REPLACE PACKAGE BODY my_test
AS
PROCEDURE do_something( pv_variable IN OUT my_out )
IS
lv_variable my_out;
BEGIN
-- Work on a local copy of the variable in question
lv_variable := 'abcdefghijklmnopqrstuvwxyz';
pv_variable := lv_variable;
END do_something;
END;
/
Then when you run this
DECLARE
lv_variable VARCHAR2(30);
BEGIN
my_test.do_something( lv_variable );
DBMS_OUTPUT.PUT_LINE( '['||lv_variable||']');
END;
/
You would get the error
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
Seems to go against the spirit of using an out parameter, but after Tony's comment this was the only thing I could think of to control data within the called code.

Resources