Oracle PL/SQL: Error returned without value on function - sql

I'm trying to create a function that will compute for factorial but it returns an error when I do a SELECT FACTORIAL('1') FROM DUAL;
It returns the heinous error:function returned without value. I tried adding an exception but it seems that it doesn't work either. Care to help?
CREATE OR REPLACE FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN NUMBER
AS var_fnumber number(2);
ctr number(2);
var_contain number(2) := 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
BEGIN
var_contain := var_contain * ctr;
DBMS_OUTPUT.put_line(var_contain);
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
END LOOP;
END; --FACTORIAL;
/

You MUST return something in a function.
SQL> CREATE OR REPLACE
2 FUNCTION FACTORIAL(
3 p_factorial INTEGER)
4 RETURN NUMBER
5 AS
6 var_fnumber NUMBER(2);
7 ctr NUMBER(2);
8 var_contain NUMBER(2) := 1;
9 BEGIN
10 FOR ctr IN 1..p_factorial
11 LOOP
12 BEGIN
13 var_contain := var_contain * ctr;
14 END;
15 END LOOP;
16 RETURN var_contain;
17 END;
18 /
Function created.
SQL>
SQL> SELECT factorial(2) FROM dual
2 /
FACTORIAL(2)
------------
2
For more details, read http://lalitkumarb.wordpress.com/2014/05/01/ora-06503-plsql-function-returned-without-value/

CREATE OR REPLACE FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN NUMBER
AS var_fnumber number;
ctr number;
var_contain number := 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
BEGIN
var_contain := var_contain * ctr;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
RETURN var_contain;
END;
END LOOP;
RETURN var_contain;
END; --FACTORIAL;
/
Was gonna say that I found it. Thank you for the answers.
As for the reason why I used varchar2, I wasn't finalizing it yet.

modified your code try this:
create or replace
FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN VARCHAR2
AS
var_contain varchar2(50):= 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
var_contain := var_contain * ctr;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RETURN O;
return var_contain;

Related

What is wrong in this PL/SQL program?

declare
p number:=371;
x number;
t number;
sum number;
begin
x:=p;
while x>0 loop
t:=x mod 10;
sum:=sum+ t**3;
x:=x/10;
end loop;
if (sum=p) then
dbms_output.put_line(p||+' '||'an armstrong number');
end if;
end;
/
sum is a keyword, just use another name for your variable, e.g. mysum.
declare
p number:=371;
x number;
t number;
mysum number;
begin
x:=p;
while x>0 loop
t:=x mod 10;
mysum:=mysum + t**3;
x:=x/10;
end loop;
if (mysum=p) then
dbms_output.put_line(p||+' '||'an armstrong number');
end if;
end;
/
You cannot use keywords as name of variables. sum is a keyword in oracle so change variable name from sum to anything else.

how to find multiple of a number using goto sql statement?

Write a PL/SQL block to display the multiples of a Given Number
without including multiples of 10 for a given range (Start Value and
End Value), using GOTO.
This is my try, but I couldn't place the goto statement in correct place:
declare
start_value number; end_value number; n number;
result;
begin
start_value:=&start_value;
end_value:=&end_value;
n :=&n;
for x in start_value..end_value loop
<<calc>>
if((x mod n)=0 and (x mod 10)!=0) then
dbms_output.put_line(x);
end if;
goto calc;
end loop;
end;
First off, this is a really bad assignment. Teaching you to use GOTO's is like teaching a naval architect to build ships without watertight bulkheads - it's Just Wrong. (sigh) But, oh well...
DECLARE
start_value NUMBER;
end_value NUMBER;
n NUMBER;
BEGIN
start_value := &start_value;
end_value := &end_value;
n := &n;
FOR x IN start_value..end_value LOOP
IF MOD(x, 10) = 0 THEN
GOTO skip_calc;
END IF;
DBMS_OUTPUT.PUT_LINE(n * x);
<<skip_calc>>
NULL;
END LOOP;
END;
The way this would normally be written is:
DECLARE
start_value NUMBER;
end_value NUMBER;
n NUMBER;
BEGIN
start_value := &start_value;
end_value := &end_value;
n := &n;
FOR x IN start_value..end_value LOOP
IF MOD(x, 10) <> 0 THEN
DBMS_OUTPUT.PUT_LINE(n * x);
END IF;
END LOOP;
END;
Shorter and easier to read.

exception handling not outputting to dbms

Here is my sql code for a function that calculates the area of a circle. I am having trouble getting a dbms_output to show the user defined exception.
I begin by declaring an exception underzero. then i raise it if the user inputs a number less than or equal to 0. In the exception i have dbms_output then return the result. It shows in the query result that the value is null, however the output isn't showing.
I have already set serveroutput on and set verify off. I don't know why it wont output anything. If i run that line alone it outputs to the dbms output window but not when the exception is raised.
create or replace function circle_area
(p_radius number)
return number
is
c_Pi Constant number := acos(-1);
v_result number(10, 2);
underzero exception;
begin
if p_radius <=0 then
raise underzero;
else
v_result := c_pi * p_radius * p_radius;
return v_result;
end if;
exception
when underzero then
dbms_output.put_line('enter number greater than 0');
return v_result;
when others then
dbms_output.put_line('Exception Location: Anonymous Block');
dbms_output.put_line(sqlcode || ': ' || sqlerrm);
return v_result;
end circle_area;
to call the function:
select circle_area(-2) from dual;
I'm not sure that I understand the problem. The code you posted will generate output to dbms_output if serveroutput is enabled...
SQL> set serveroutput on;
SQL> create or replace function circle_area
2 (p_radius number)
3 return number
4 is
5 c_Pi Constant number := acos(-1);
6 v_result number(10, 2);
7 underzero exception;
8 begin
9 if p_radius <=0 then
10 raise underzero;
11 else
12 v_result := c_pi * p_radius * p_radius;
13 return v_result;
14 end if;
15
16 exception
17 when underzero then
18 dbms_output.put_line('enter number greater than 0');
19 return v_result;
20 when others then
21 dbms_output.put_line('Exception Location: Anonymous Block');
22 dbms_output.put_line(sqlcode || ': ' || sqlerrm);
23 return v_result;
24 end circle_area;
25 /
Function created.
SQL> select circle_area(-2) from dual;
CIRCLE_AREA(-2)
---------------
enter number greater than 0
I'm assuming that this is part of a homework assignment and not a real problem that you're facing. In reality, you'd never write code whose primary purpose was to write to dbms_output and you would never, ever have an exception handler that only wrote to dbms_output.

Sum of Digits in Pl/SQL (Error In extracting Digits)

I have Written Following Code :
DECLARE
n integer;
s integer;
d integer;
BEGIN
n:=&n;
while n!=0 loop
d:=mod(n,10);
s:=s+d;
n:=n/10;
end loop;
dbms_output.put_line('output :'||s);
end;
/
Input Value : 1234
Output Value : 4321 (Perfect What I want)
But When I Tried with following (I found incorrect output)
Input value : 5678
Output : 88761
Expected Output : 8765
The code you provided didn't work for me but the error is because it is rounding this operation:
n:=n/10;
If you change it to this it should work:
n:=floor(n/10); OR n:=trunc(n/10);
However it's not working for me, I needed to add something to s:=s+d. Here's my code:
DECLARE
n INTEGER;
s INTEGER:= 0;
d INTEGER;
i INTEGER:= 0;
BEGIN
n:= 5678;
i:= length(to_char(n))-1;
WHILE n!=0 LOOP
d:=mod(n,10);
s:=s+(d*power(10,i));
i := i - 1;
n:= trunc(n/10);
END LOOP;
dbms_output.put_line('output :'||s);
END;
/
You should initialize s and a few more changes.
DECLARE
n INTEGER;
s integer := 0;
d integer;
BEGIN
n:=&n;
while n!=0 loop
d:=mod(n,10);
s:=(s*10)+d;
n:=floor(n/10);
end loop;
dbms_output.put_line('output :'||s);
END;
/

how can we get the value of of VARRAY from IN Parameter in procedure

I am new to PL/SQL... In Varray how can i get multiple value from IN parameter..... else Is there another ways to get the values...
I want to interate the values through VArray... if any other options then its fine..
coding:
CREATE OR REPLACE
PROCEDURE dynamic_query_build(
vr_plan_sku_id IN VARCHAR2 )
IS
type plan_sku_id_array IS VARRAY(999) OF VARCHAR2(5000);
plan_sku_id plan_sku_id_array;
total INTEGER;
vrx_plan_sku_id VARCHAR2(3000);
BEGIN
vrx_plan_sku_id:= REPLACE(vr_plan_sku_id,',',chr(39)||','||chr(39));
plan_sku_id := plan_sku_id_array(chr(39)||vrx_plan_sku_id||chr(39));
total := plan_sku_id.count;
FOR i IN 1 .. total
LOOP
dbms_output.put_line(plan_sku_id(i));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END dynamic_query_build;
Execution:
set serveroutput on;
declare
vr_plan_sku_id varchar2(200) := '5863314,5863315';
BEGIN
dynamic_query_build(vr_plan_sku_id);
END;
/
My Output:
anonymous block completed
'5863314','5863315'
Expected output:
5863314
5863315
now it is considering as single value....
I created anonymous block with procedure dynamic_query_build. Added there code, that will split VARCHAR2 variable into varray.
I think, the key to your question is this line - plan_sku_id.EXTEND();
You can extend varray dynamically, but only till it reaches defined maximum (in your case - 999).
DECLARE
vr_plan_sku_id varchar2(200) := '5863314,5863315';
PROCEDURE dynamic_query_build(
vr_plan_sku_id IN VARCHAR2 )
IS
type plan_sku_id_array IS VARRAY(999) OF VARCHAR2(5000);
plan_sku_id plan_sku_id_array;
total INTEGER;
position PLS_INTEGER := 0;
last_position PLS_INTEGER := 1;
tmp VARCHAR2(5000);
counter PLS_INTEGER := 1;
BEGIN
plan_sku_id := plan_sku_id_array();
LOOP
position := INSTR(vr_plan_sku_id, ',', last_position);
IF position > 0 THEN
tmp := SUBSTR(vr_plan_sku_id, last_position, position - last_position);
last_position := position + 1;
ELSE
tmp := SUBSTR(vr_plan_sku_id, last_position);
END IF;
plan_sku_id.EXTEND();
plan_sku_id(counter) := tmp;
counter := counter + 1;
EXIT WHEN position = 0 OR counter > 10;
END LOOP;
total := plan_sku_id.count;
FOR i IN 1 .. total
LOOP
dbms_output.put_line(plan_sku_id(i));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END dynamic_query_build;
BEGIN
dynamic_query_build(vr_plan_sku_id);
END;
/
Put a replace in the dbms_output statement this will eliminate the quotes from the string
....
dbms_output.put_line replace (replace (plan_sku_id(i), '''' ))',',chr(10);
.....