I am trying to write a program for Armstrong number in PL/SQL.Can anyone tell me where i am wrong? - oracle

while N !=0
LOOP
R:=MOD(N,10);
R1:=power(R,3);
A:=A+R1;
N:=TRUNC(N/10);
END LOOP;
After this it comes IF N=A THEN
SYS.DBMS_OUTPUT.PUT_LINE(' number is armstrong ');
ELSE
SYS.DBMS_OUTPUT.PUT_LINE(' number is not an armstrong ');

Your problem is when you compare (N=A) because N is zero at the end of LOOP. Then you must compare A with the original number entered, (NOrig=A).
This procedure you can help:
create or replace procedure amstrong_number(pNumber int)
is
NOrig int:=0;
N int:=0;
R int:=0;
R1 int:=0;
A int:=0;
begin
NOrig:=pNumber;
N:=pNumber;
WHILE N!= 0
LOOP
R:=MOD(N,10);
R1:=POWER(R,3);
A:=A+R1;
N:=TRUNC(N/10);
END LOOP;
IF NOrig = A THEN
dbms_output.put_line(' number is amstrong ');
ELSE
dbms_output.put_line(' number is not an amstrong ');
END IF;
end;
Regards

In a comment you say you want to take user input from the keyboard. It is not clear how you plan to do that; in general, PL/SQL does not have facilities for interaction with end users, it is a language for processing on the server.
One way to have the user provide a number is to have a procedure with an in parameter. Below is one example of how you can do it. You must compile the procedure first (for example, I saved it in a script, "Armstrong.sql", and then I ran the command "start Armstrong" in SQL*Plus). Then the user can use the procedure, which I called is_Armstrong, from SQL*Plus or a graphical interface like SQL Developer or Toad, like this: exec is_Armstrong(...) where in parentheses is the user's input number.
I built in two application exception checks - for negative or non-integer numbers and for numbers that are too long (more than 20 digits). I wrote it for Armstrong numbers of arbitrary length (<= 20), limiting it to three digits doesn't save almost any work so why not make it general. There are other possible application exceptions - for example, what if the user inputs a string instead of a number? I didn't handle all the errors - the very last example below shows an unhandled one. Write your own error handling code for whatever else you want to handle explicitly.
Content of Armstrong.sql:
create or replace procedure is_Armstrong(p_input_number number)
as
l_string varchar2(20);
l_sum number := 0;
l_loop_counter number;
l_len number;
not_a_positive_integer exception;
number_too_large exception;
begin
l_string := to_char(p_input_number);
l_len := length(l_string);
if p_input_number <= 0 or p_input_number != floor(p_input_number) then
raise not_a_positive_integer;
elsif l_len > 20 then
raise number_too_large;
end if;
for l_loop_counter in 1..l_len
loop
l_sum := l_sum + power(to_number(substr(l_string, l_loop_counter, 1)), l_len);
end loop;
if p_input_number = l_sum then
dbms_output.put_line('Number ' || l_string || ' is an Armstrong number.');
else
dbms_output.put_line('Number ' || l_string || ' is not an Armstrong number.');
end if;
exception
when not_a_positive_integer then
dbms_output.put_line('Input number must be a positive integer.');
when number_too_large then
dbms_output.put_line('Input number must be no more than twenty digits.');
end;
/
Compiling the procedure:
SQL> start Armstrong.sql
Procedure created.
Elapsed: 00:00:00.03
Usage examples:
SQL> exec is_Armstrong(-33);
Input number must be a positive integer
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.08
SQL> exec is_Armstrong(1.5);
Input number must be a positive integer
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.08
SQL> exec is_Armstrong(1234512345123451234512345);
Input number must be no more than twenty digits
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
SQL> exec is_Armstrong(3);
Number 3 is an Armstrong number.
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> exec is_Armstrong(100);
Number 100 is not an Armstrong number.
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> exec is_Armstrong(371);
Number 371 is an Armstrong number.
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> exec is_Armstrong('abc')
BEGIN is_Armstrong('abc'); END;
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 1
Elapsed: 00:00:00.00

Related

Procedure gives empty result when called

I have created a simple procedure to reverse a number in PL/SQL. The procedure executes fine, but the result doesn't get print. Here's the proc,
CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
IS
OperInput NUMBER;
MYREMAINDER NUMBER;
MYRESULT NUMBER;
BEGIN
OperInput:=myinput;
while OperInput!=0 LOOP
MYREMAINDER:=mod(OperInput,10);
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
OperInput:=TRUNC(OperInput/10);
end LOOP;
finalresult:=MYRESULT;
END;
Procedure, when executed works fine. But, when I call on the procedure by the following code,
DECLARE
ENTER NUMBER;
finalresult NUMBER;
BEGIN
ENTER:=&ENTER;
SAMPLE_REV(ENTER,finalresult);
dbms_output.put_line('Output is '|| finalresult);
END;
The result is empty as,
Output is
PL/SQL procedure successfully completed.
I can't come to know the error here, if any. And thanks for the help.
the procedure is using MYRESULT before it is initialized hence null. So this line:
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
is essentially
MYRESULT:=(<<<NULL>>>*10)+MYREMAINDER;
So null overall.
Just adding a :=0 to the declaration will get it working. Also add the set serveroutput on
SQL>set serveroutput on
SQL>CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
2 IS
3 OperInput NUMBER;
4 MYREMAINDER NUMBER;
5 MYRESULT NUMBER :=0;
6 BEGIN
7 OperInput:=myinput;
8
9 while OperInput!=0 LOOP
10
11 MYREMAINDER:=mod(OperInput,10);
12 MYRESULT:=(MYRESULT*10)+MYREMAINDER;
13 OperInput:=TRUNC(OperInput/10);
14
15 end LOOP;
16
17 finalresult:=MYRESULT;
18
19 END;
20* /
Procedure SAMPLE_REV compiled
SQL>DECLARE
2 ENTER NUMBER;
3 finalresult NUMBER;
4 BEGIN
5 ENTER:=&ENTER;
6 SAMPLE_REV(ENTER,finalresult);
7 dbms_output.put_line('Output is '|| finalresult);
8 END;
9 /
Enter value for ENTER: 987
Output is 789
PL/SQL procedure successfully completed.
SQL>
In order to view the output of a PL/SQL procedure using dbms_ouput.put_line, run the following command in your session window:
SET SERVEROUTPUT ON;
Should do the trick :)
I see your calculation is not correct. I have added additional output in the procedure to see what it is printing.
MYRESULT itslef is empty and hence you see the output is empty.
set serveroutput on;
CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
IS
OperInput NUMBER;
MYREMAINDER NUMBER;
MYRESULT NUMBER;
BEGIN
OperInput:=myinput;
while OperInput!=0 LOOP
MYREMAINDER:=mod(OperInput,10);
dbms_output.put_line('remainder ' || MYREMAINDER);
dbms_output.put_line('in ' || MYRESULT);
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
dbms_output.put_line('out ' || MYRESULT);
OperInput:=TRUNC(OperInput/10);
end LOOP;
finalresult:=MYRESULT;
END;
This line is the problem:
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
On the first iteration MYRESULT is null. So the MYRESULT*10 will be also null. And null + MYREMAINDER = null;
Initialize MYRESULT in the declare section to 0;

Plsql procedure and exception

Write a PL/SQL procedure: when somebody enters a number, it'll print that number. Otherwise, it'll display error message.
You could also try to convert your input string to a number, and then catch the potential conversion error
Create Or Replace Procedure is_number(p_num varchar2) Is
v_num Number;
Begin
v_num := to_number(p_num);
dbms_output.put_line(v_num);
Exception
When VALUE_ERROR Then
dbms_output.put_line(p_num || ' is not a number');
End is_number;
Not too smart, but will get you started.
Using regular expressions (REGEXP_LIKE), check whether value is a number, consisting of
any number of digits [0-9]+
optionally |
followed by a decimal point . (backslash is here to escape it, as dot represents any character in a regular expression)
followed by any number of digits [0-9]+
^ and $ are anchors for beginning and end of entered value (i.e. it must begin and end with a digit)
Here it is:
SQL> create or replace procedure p_test (par_input in varchar2)
2 is
3 begin
4 if regexp_like(par_input, '^[0-9]+|(\.[0-9]+)$') then
5 dbms_output.put_line(par_input);
6 else
7 dbms_output.put_line('Error');
8 end if;
9 end;
10 /
Procedure created.
SQL> set serveroutput on;
SQL>
SQL> begin
2 p_test('2');
3 p_test('2.13');
4 p_test('x');
5 p_test('&#');
6 end;
7 /
2
2.13
Error
Error
PL/SQL procedure successfully completed.
SQL>
You can do it like this,
set serveroutput on;
BEGIN
DBMS_OUTPUT.PUT_LINE('&number'+0);
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('Error');
END;
/

Procedure add plus one (+1) everty time is called in PL/SQL

I have to do a procedure that add plus 1 to the previous value every time its is called in PL/SQL language. But I don't know how to do that.
I mean, if the procedure is call "plus1":
First execution:
exec plus1
will return value 1.
Second execution:
exec plus1
will return value 2.
And go on
The best way is to create a sequence, as noticed in comments:
create sequence my_seq;
To call the sequence in PL/SQL:
my_var := my_seq.nextval;
To call in SQL:
select t.*, my_seq.nextval from table t;
In the SQL query, a new value will be generated for each line.
If you don't need a sequence, and you don't need to store the value between sessions, create a package:
create or replace package my_package as
function get_next_value return number;
end my_package;
/
create or replace package body my_package as
current_num number := 0;
function get_next_value return number is
begin
current_num := current_num + 1;
return current_num;
end;
end my_package;
/
And then call my_package.get_next_value.
It is not entirely clear what you need. Here is one approach, assuming you need a session variable, initialized to zero at the start of the session, which you can call as needed, and is increased only when a procedure is executed. This is different from a function that increments the variable and returns it at the same time.
If you need to access the variable in SQL (rather than just in PL/SQL), you need to write a wrapper function that returns the value; I included the wrapper function in the code below.
create or replace package silly_p as
v number := 0;
function show_v return number;
procedure increment_v;
end;
/
create or replace package body silly_p as
function show_v return number is
begin
return v;
end show_v;
procedure increment_v is
begin
v := v+1;
end increment_v;
end silly_p;
/
Here is a SQL*Session demonstrating the compilation of this package and then its use - I access the variable both through SQL SELECT and from PL/SQL (with DBMS_OUTPUT) to demonstrate both access methods. Notice how the value is unchanged between calls to the procedure, and increases by one every time the procedure is executed.
SQL> create or replace package silly_p as
2 v number := 0;
3 function show_v return number;
4 procedure increment_v;
5 end;
6 /
Package created.
Elapsed: 00:00:00.03
SQL>
SQL> create or replace package body silly_p as
2 function show_v return number is
3 begin
4 return v;
5 end show_v;
6 procedure increment_v is
7 begin
8 v := v+1;
9 end increment_v;
10 end silly_p;
11 /
Package body created.
Elapsed: 00:00:00.00
SQL> select silly_p.show_v from dual;
SHOW_V
----------
0
1 row selected.
Elapsed: 00:00:00.00
SQL> exec dbms_output.put_line(silly_p.v)
0
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
SQL> exec silly_p.increment_v
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.04
SQL> select silly_p.show_v from dual;
SHOW_V
----------
1
1 row selected.
Elapsed: 00:00:00.14
SQL> exec silly_p.increment_v
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.07
SQL> exec dbms_output.put_line(silly_p.v)
2
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.07
SQL>
I've answered a similar question recently (have a look here); basically, you need to store current value somewhere (a table might be a good choice) and create a function (or, in your case, a procedure) that returns the next number.
How to convert the function I wrote to a procedure? Use it as a wrapper.
Here's the whole example:
SQL> CREATE TABLE broj (redni_br NUMBER NOT NULL);
Table created.
SQL>
SQL> CREATE OR REPLACE FUNCTION f_get_broj
2 RETURN NUMBER
3 IS
4 PRAGMA AUTONOMOUS_TRANSACTION;
5 l_redni_br broj.redni_br%TYPE;
6 BEGIN
7 SELECT b.redni_br + 1
8 INTO l_redni_br
9 FROM broj b
10 FOR UPDATE OF b.redni_br;
11
12 UPDATE broj b
13 SET b.redni_br = l_redni_br;
14
15 COMMIT;
16 RETURN (l_redni_br);
17 EXCEPTION
18 WHEN NO_DATA_FOUND
19 THEN
20 LOCK TABLE broj IN EXCLUSIVE MODE;
21
22 INSERT INTO broj (redni_br)
23 VALUES (1);
24
25 COMMIT;
26 RETURN (1);
27 END f_get_broj;
28 /
Function created.
SQL>
SQL> CREATE PROCEDURE p_get_Broj
2 AS
3 BEGIN
4 DBMS_OUTPUT.put_line (f_get_broj);
5 END;
6 /
Procedure created.
SQL>
SQL> EXEC p_get_broj;
PL/SQL procedure successfully completed.
SQL> set serveroutput on
SQL> EXEC p_get_broj;
2
PL/SQL procedure successfully completed.
SQL> EXEC p_get_broj;
3
PL/SQL procedure successfully completed.
SQL> EXEC p_get_broj;
4
PL/SQL procedure successfully completed.
I believe you need a session a variable like mathguy's assumption above. You can try below code and understand how it works. Note that each DB session could have different value to the NUM_VAR variable in var_pkg package depending on how many times the procedure below was executed for each session.
CREATE OR REPLACE PACKAGE var_pkg
IS
num_var NUMBER := 0;
PROCEDURE set_num_var(p_number NUMBER);
FUNCTION get_num_var RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY var_pkg
IS
PROCEDURE set_num_var(p_number NUMBER)
IS
BEGIN
num_var := p_number;
END;
FUNCTION get_num_var RETURN NUMBER
IS
BEGIN
RETURN num_var;
END;
END;
/
CREATE PROCEDURE plus1
IS
v_num NUMBER;
BEGIN
v_num := var_pkg.get_num_var + 1;
var_pkg.set_num_var(v_num);
DBMS_OUTPUT.PUT_LINE(v_num);
END;
/
To run the procedure,
exec plus1;
or
BEGIN
plus1;
END;
/
And in case you want to know the current value of the variable, you can query it using below code,
SELECT var_pkg.get_num_var
FROM dual;

asking for user input in PL/SQL

I am new to PL/SQL and I am stuck on some code.
I am wanting to ask the user for a number and then I want to be able to use this number in an IF THEN statement to verify if the number is greater than or less than 20.
I am stuck on how to obtain user input and once I have it, I can store it and give it back to the user and verify its greater than or less than 20.
DECLARE
a number(2) := 10;
BEGIN
a:= 10;
-- check the boolean condition using if statement
IF( a < 20 ) THEN
-- if condition is true then print the following
dbms_output.put_line('a is less than 20 ' );
END IF;
dbms_output.put_line('value of a is : ' || a);
END;
/
SQL> set serveroutput on; -- for "dbms_output.put_line" to take effect
SQL> DECLARE
a number := &i_nr; -- there's no need to restrict a non-decimal numeric variable to a length
BEGIN
--a:= 10; --no need this when initialization is in declaration section
-- check the boolean condition using if statement
IF( a < 20 ) THEN
-- if condition is true then print the following
dbms_output.put_line('a is less than 20 ' );
END IF;
dbms_output.put_line('value of a is : ' || a);
END;
/
-- it prompts you for value of &i_nr "enter a numeric value, for example 10", for string values it must be in quotes '&i_str'
In SQLPlus, you'd use "&"; in my example, it is && so that I wouldn't have to enter the same value several times (i.e. every time "a" is referenced):
SQL> begin
2 if &&a < 20 then
3 dbms_output.put_line('a is less than 20');
4 end if;
5 dbms_output.put_line('value of a is: ' || &&a);
6 end;
7 /
Enter value for a: 5
old 2: if &&a < 20 then
new 2: if 5 < 20 then
old 5: dbms_output.put_line('value of a is: ' || &&a);
new 5: dbms_output.put_line('value of a is: ' || 5);
a is less than 20
value of a is: 5
PL/SQL procedure successfully completed.
SQL>
Though, I'd say that you'd rather create a procedure with an IN parameter, such as
SQL> create or replace procedure p_test (par_a in number) is
2 begin
3 if par_a < 20 then
4 dbms_output.put_line('a is less than 20');
5 end if;
6 dbms_output.put_line('value of a is: ' || par_a);
7 end;
8 /
Procedure created.
SQL> exec p_test(15);
a is less than 20
value of a is: 15
PL/SQL procedure successfully completed.
SQL> exec p_test(34);
value of a is: 34
PL/SQL procedure successfully completed.
SQL>

sql plus warning in procedure. procedure created with compilation error. (procedure with parameter)

hey i am trying to do a pl sql program with the help of procedure. i want to check if number given by user is even or odd using procedure but i am getting an warning : procedure created with compilation error .
create or replace procedure even( a in out number)
as n number :=&n;
begin
if(n,2)=0 then
dbms_output.put_line('even');
else
dbms_output.put_line('odd');
end if;
end;
/
It is meaningless to compile the procedure each time you get user input.You should rather be doing the following.
Compile the procedure without any substitution variables. The parameter should be just IN and not IN OUT unless you want to modify its value inside the procedure.
CREATE OR replace PROCEDURE Even(n IN NUMBER)
AS
BEGIN
IF MOD(n, 2) = 0 THEN
dbms_output.put_line('even');
ELSE
dbms_output.put_line('odd');
END IF;
END;
/
Then execute this compiled procedure as many times as you like by passing user input.
SQL> SET SERVEROUTPUT ON;
SQL> EXEC even ( &n );
Enter value for n: 5
odd
PL/SQL procedure successfully completed.
SQL> EXEC even ( &n );
Enter value for n: 4
even
PL/SQL procedure successfully completed.
Why don't you use you mod function:
if mod(a,2)=0 then
dbms_output.put_line('even');
else
dbms_output.put_line('odd');
end if;
I think you put "n" instead of "a"
Consider using a function instead; in my opinion, it is a better option for such a task than a procedure.
A natural choice would be a function that returns Boolean:
SQL> create or replace function f_is_even (par_n in number)
2 return boolean
3 is
4 begin
5 return mod(par_n, 2) = 0;
6 end;
7 /
Function created.
You'd then use it in some PL/SQL code as the following example (yes, it looks stupid because it appears that it does exactly what your procedure does, but note - this is just an example; in real life, you'd use it in smarter way):
SQL> begin
2 if f_is_even(6) then
3 dbms_output.put_Line('even');
4 else
5 dbms_output.put_Line('odd');
6 end if;
7 end;
8 /
even
PL/SQL procedure successfully completed.
Drawback of such a function is that you can't use it in SQL (but, as I said, PL/SQL):
SQL> select f_is_even(5) from dual;
select f_is_even(5) from dual
*
ERROR at line 1:
ORA-06552: PL/SQL: Statement ignored
ORA-06553: PLS-382: expression is of wrong type
A possible "workaround" is to create a procedure that doesn't return Boolean but, for example, number (0 for "false" and 1 for "true") or string (N for "false, no" and Y for "true, yes"). For example:
SQL> create or replace function f_is_even_01 (par_n in number)
2 -- returns 1 if number is even; returns 0 if number is odd
3 return number
4 is
5 begin
6 return case when mod(par_n, 2) = 0 then 1
7 else 0
8 end;
9 end;
10 /
Function created.
SQL> select f_is_even_01(5) r1,
2 f_is_even_01(6) r2
3 from dual;
R1 R2
---------- ----------
0 1
There's nothing wrong in using a procedure; I just thought that you might want to hear another opinion.

Resources