I have been trying to write a code to print below pattern
Expected output :
***
***
***
***
***
***
***
But I know only one vertical pattern how to print it
DECLARE
v_num number :=7;
BEGIN
FOR vcount in 1..v_num LOOP
DBMS_OUTPUT.PUT_LINE('*');
END LOOP;
END;
/
Need your input how to achieve expected output …
Do you really need PL/SQL?
SQL> select '***'
2 from dual
3 connect by level <= 7;
'**
---
***
***
***
***
***
***
***
7 rows selected.
SQL>
If it must be PL/SQL:
SQL> begin
2 for i in 1 .. 7 loop
3 dbms_output.put_line('***');
4 end loop;
5 end;
6 /
***
***
***
***
***
***
***
PL/SQL procedure successfully completed.
SQL>
If you want to make it generic, create a stored procedure:
SQL> create or replace procedure p_pattern
2 (par_character in varchar2, par_number in number, par_rows in number)
3 is
4 begin
5 for i in 1 .. par_rows loop
6 dbms_output.put_line(rpad(par_character, par_number, par_character));
7 end loop;
8 end;
9 /
Procedure created.
SQL> exec p_pattern('=', 5, 3);
=====
=====
=====
PL/SQL procedure successfully completed.
SQL> exec p_pattern('*', 3, 7);
***
***
***
***
***
***
***
PL/SQL procedure successfully completed.
SQL>
Related
I am calling a stored procedure from Python program.
There is an issue that happens on certain values.
For example it fails when i send values 2020,2017 but it succeeds wen I send 2010,2050 etc. What can be the issue?
DB Version: NLSRTL Version 11.2.0.4.0 - Production
Oracle_cx: latest
Procedure parameter that causes the issue : P_FILE_YEAR IN NUMBER
Error Message: ERROR 1520: File No:ORA-06502: PL/SQL: numeric or value error: number precision too large
It fails in the following exception:
BEGIN
SELECT MAX(mlal_file_no) + 1
INTO ln_file_no
FROM doc_mail_allocation
WHERE mlal_file_year = P_FILE_YEAR
AND std_file_type_code = 2 ;
EXCEPTION
WHEN no_data_found THEN
ln_file_no := 1 ;
WHEN OTHERS THEN
p_error_code := 1 ;
p_error_msg := 'ERROR 1520: File No:'||SQLERRM||' AND flal_file_year = '||P_FILE_YEAR;
RETURN ;
END ;
Looks like this:
Sample data:
SQL> select * From doc_mail_allocation;
MLAL_FILE_YEAR STD_FILE_TYPE_CODE MLAL_FILE_NO
-------------- ------------------ ------------
2010 2 100
2020 2 999
Your code:
SQL> declare
2 ln_file_no number(3);
3 begin
4 SELECT MAX(mlal_file_no) + 1
5 INTO ln_file_no
6 FROM doc_mail_allocation
7 WHERE mlal_file_year = &P_FILE_YEAR
8 AND std_file_type_code = 2 ;
9 dbms_output.put_line('result = ' || ln_file_no);
10 end;
11 /
Enter value for p_file_year: 2010
result = 101
PL/SQL procedure successfully completed.
SQL> /
Enter value for p_file_year: 2020
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 4
SQL>
See the difference & error cause? If you declared a variable as "too small" (number(3)), for year 2020 MAX(mlal_file_no) + 1 equals 1000 and it can't fit into such a variable.
Solution? Enlarge ln_file_no, or check why this happens (if it shouldn't) - then there's error in data.
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
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
I have the below pl/sql procedure
PROCEDURE insert_p(
p_batch_rec IN ra_batches%rowtype,
p_batch_id OUT NOCOPY ra_batches.batch_id%type,
p_name OUT NOCOPY ra_batches.name%type
)
batch_id is NUMBER(18,0) and p_name is VARCHAR2(50 CHAR)
I'm calling the procedure with
insert_p (l_batch_rec, p_batch_id, p_name);
where p_batch_id:=NULL and p_name:=NULL
I get the conversion error only on the first time I run the procedure. If I run again without changes, it runs fine. To reproduce the error, I disconnect and connect again.
Any ideas why does this error come and how should I resolve the same???
Does the error happen in the initialization part of a package that is used by the function?
You should be able to easily find exactly where the error happens. By default, Oracle will display the object and the line number of the error. (Although, to my great frustration, I find that it is very common for people to write when others then [poor logging that throws out line number].)
SQL> --Create package
SQL> create or replace package test_package is
2 procedure test_procedure;
3 conversion_error number;
4 end;
5 /
Package created.
SQL> --Create package body. Note the initialization part that will fail.
SQL> create or replace package body test_package is
2 procedure test_procedure is
3 begin
4 null;
5 end;
6 begin
7 conversion_error := 'This is not a number';
8 end;
9 /
Package body created.
SQL> --This will fail the first time
SQL> begin
2 test_package.test_procedure;
3 end;
4 /
begin
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "JHELLER.TEST_PACKAGE", line 7
ORA-06512: at line 2
SQL> --But will now work until you reconnect, or run DBMS_SESSION.RESET_PACKAGE.
SQL> begin
2 test_package.test_procedure;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
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.