pl/sql even and odd sum block - sql

I have a pl/sql programming question: For numbers between 1..50, you need to multiply even numbers by five, odd numbers by 3 and then find sum of all the numbers in the result.
So I had this so far
DECLARE
ln_num NUMBER :=0;
ln_num1 NUMBER :=0;
ln_num2 NUMBER :=0;
BEGIN
for i in 1..50 loop
if mod(i,2) =0 then
ln_num:=i*5;
elsif mod(i,2) = 1 then
ln_num1:=i*3;
ln_num2 := ln_num+ln_num1;
dbms_output.put_line(ln_num2);
end if;
end loop;
END;
This gives me a last list of numbers but i need the sum of all of them. I was wondering what I was missing and how do I fix this?
Thanks

create or replace function odd_even_Numbers(num number)
return varchar2 is
value1 number;
message varchar2(30);
a number;
begin
a:=num;
loop
select abs(REMAINDER(a, 2)) into value1 from dual;
if (value1=1) then
message:= 'odd number';
dbms_output.put_line (a||'-----'||message);
a:=a+1;
else
message:='even number';
dbms_output.put_line (a||'-----'||message);
a:=a+1;
end if;
exit when a=20;
end loop;
message:='done well';
return message;
end;

SQL> DECLARE
2 ln_num NUMBER :=0;
3 ln_num1 NUMBER :=0;
4 ln_num2 NUMBER :=0;
5
6 BEGIN
7 for i in 1..50 loop
8
9 if mod(i,2) =0 then
10 ln_num:=ln_num+i*5; -- changes
11
12 elsif mod(i,2) = 1 then
13 ln_num1:=ln_num1+i*3; -- changes
14
15
16 end if;
17 end loop;
18 ln_num2 := ln_num+ln_num1;
19 dbms_output.put_line(' the result is ' || ln_num2);
20
21 END;
22
23
24 /
the result is 5125
PL/SQL procedure successfully completed.

Related

How to iterate over binary string in Oracle?

enter image description here
declare
str varchar2(2000) := :inputstr;
v_len number;
currChar CHAR(1);
begin
v_len := length(str);
for i in 1..v_len
Loop
currChar := substr(str,i,1);
if currChar = 1 then
dbms_output.put_line('curr index' || i);
end if;
End loop;
end;
When I pass '000111000' as input to IN_STRING variable , it trims the string and behaves very unusually.Please suggest some good approaches to iterate over binary strings like this.I am expecting output as 4,5,6 from above operation.
EDIT1:
Please don't directly input the string as str varchar2(2000) := '000111000';
Instead input it from bind variable as I mentioned above.
Your code works so long as you pass in a VARCHAR2 data type (and not a NUMBER).
You can also tidy up the code passing in the bind variable only once and using CONSTANTs to hold the values that are constant:
VARIABLE in_string VARCHAR2;
DECLARE
c_string CONSTANT VARCHAR2(200) := :in_string;
c_length CONSTANT PLS_INTEGER := LENGTH(c_string);
v_out CHAR(1);
BEGIN
FOR i IN 1..c_length
LOOP
v_out := SUBSTR(c_string,i,1) ;
DBMS_OUTPUT.PUT_LINE(v_out);
END LOOP;
END;
/
Which outputs:
0
0
1
1
1
0
0
0
db<>fiddle here
Shouldn't behave unusual, unless datatype of in_string variable is NUMBER (then leading zeros don't have any meaning) - switch to VARCHAR2.
Illustration:
NUMBER variable datatype
value you enter
result - really, missing leading zeros
Otherwise, it works OK (this is SQL*Plus so I used substitution variable):
SQL> DECLARE
2 v_length NUMBER (10);
3 v_out VARCHAR2 (20);
4 BEGIN
5 v_length := LENGTH ( '&&in_string');
6
7 FOR i IN 1 .. v_length
8 LOOP
9 v_out := SUBSTR ( '&&in_string', i, 1);
10 DBMS_OUTPUT.PUT_LINE (v_out);
11 END LOOP;
12 END;
13 /
Enter value for in_string: 00111000
0
0
1
1
1
0
0
0
PL/SQL procedure successfully completed.
Another option (if you're interested in it) doesn't require PL/SQL:
SQL> SELECT SUBSTR ( '&&in_string', LEVEL, 1) val
2 FROM DUAL
3 CONNECT BY LEVEL <= LENGTH ( '&&in_string');
V
-
0
0
1
1
1
0
0
0
8 rows selected.
SQL>

PL/SQL CREATE PROCEDURE - factorial

I don't know what's wrong with my code block to create a procedure to find out the factorial of a number. Thank you.
Question 1: write a stored procedure that gets an integer number n and calculates and displays its factorial.
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE factorial_number(
n NUMBER) AS
factorial NUMBER;
num Number;
BEGIN
FOR i IN REVERSE 1..n LOOP
num := i - 1;
factorial := factorial * num;
END LOOP;
DBMS_OUTPUT.PUT_LINE (factorial);
EXCEPTION
WHEN OTHERS
THEN DBMS_OUTPUT.PUT_LINE ('Error!');
END;
/
BEGIN
factorial_number(5);
END;
/
You're failing to initialize the local variable factorial. Uninitialized variables are initially null and multiplying null by any value produces null.
I don't see why you'd want your loop to go in reverse order. It doesn't matter since multiplication is communitive but it it unlikely to make your code easier to read/ debug/ follow.
You don't want to subtract 1 from the value you are multiplying by on each iteration of the loop. When i = 1, for example, you're multiplying factorial by 0 which means that (assuming you initialize factorial), you'd always end up with 0. You want to multiply by i so there is no need for the local variable num.
If I make those fixes
CREATE OR REPLACE PROCEDURE factorial_number(
n NUMBER)
AS
factorial NUMBER := 1; -- Initialize
BEGIN
FOR i IN 1..n LOOP -- Loop normally
dbms_output.put_line( 'Beginning iteration ' || i || ' of loop. ' ||
'Factorial = ' || factorial ||
' multiplying by ' || i );
factorial := factorial * i; -- Multiply by i not i-1
END LOOP;
DBMS_OUTPUT.PUT_LINE (factorial);
EXCEPTION
WHEN OTHERS
THEN DBMS_OUTPUT.PUT_LINE ('Error!');
END;
Then
BEGIN
factorial_number(5);
END;
will print out 120 (5*4*3*2*1).
I'm also adding an additional dbms_output line to print out the current state of the variables on each iteration of the loop. That's a relatively old-school method of debugging. In the modern world, you'd walk through the code with a debugger where you can see the values of your local variables but introductory classes may not teach debugger usage initially.
How about
SQL> CREATE OR REPLACE PROCEDURE factorial_number (n NUMBER)
2 AS
3 factorial NUMBER := 1;
4 BEGIN
5 FOR i IN 1 .. n
6 LOOP
7 factorial := factorial * i;
8 END LOOP;
9
10 DBMS_OUTPUT.PUT_LINE (factorial);
11 END;
12 /
Procedure created.
SQL>
SQL> BEGIN
2 factorial_number (5);
3 END;
4 /
120
PL/SQL procedure successfully completed.
SQL>

Number of rows inserted/updated in utl_file

How do i print number of rows in utl_file.
If i am using dbms_output.put_line('Total record'||'|'||SQL%ROWCOUNT);
and
If i am ​using dbms_output.put_line('Total record'||'|'||To_char(SQL%ROWCOUNT));
Compiler saying wrong argument is passed. nothing is reflecting
and
utl_file.put(file_handele,'total roecord' ||'|'|| SQL%ROWCOUNT);
only total record is reflecting.
please help new to psql
What do you call "number of rows in utl_file"?
You said that 1st and 2nd statements are invalid because compiler is complaining. It is not for me, so I kind of doubt what you claim:
SQL> begin
2 -- your 1st statement:
3 dbms_output.put_line('Total record'||'|'||SQL%ROWCOUNT);
4
5 -- your 2nd statement:
6 dbms_output.put_line('Total record'||'|'||To_char(SQL%ROWCOUNT));
7 end;
8 /
Total record|
Total record|
PL/SQL procedure successfully completed.
As of the 3rd statement:
SQL> declare
2 file_handele utl_file.file_type;
3 begin
4 file_handele := utl_file.fopen('EXT_DIR', 'test.txt', 'w');
5
6 -- your 3rd statement, literally, with typos:
7 utl_file.put(file_handele,'total roecord' ||'|'|| SQL%ROWCOUNT);
8
9 utl_file.fclose(file_handele);
10 end;
11 /
PL/SQL procedure successfully completed.
SQL> $type c:\temp\test.txt
total roecord|
SQL>
All 3 statements are OK (i.e. they don't fail, they don't raise an error), but the question is: which problem are you trying to solve? Display number of rows written into a file using UTL_FILE package? If so, you should have posted that piece of code as well.
Anyway: one option is to literally count them. For example:
SQL> declare
2 i number := 0; -- this is the counter
3 file_handele utl_file.file_type;
4 begin
5 file_handele := utl_file.fopen('EXT_DIR', 'test.txt', 'w');
6
7 for cur_r in (select dname from dept) loop
8 utl_file.put(file_handele, cur_r.dname || utl_tcp.crlf);
9 i := i + 1; -- increment the counter
10 end loop;
11
12 -- your 3rd statement, literally, with typos:
13 utl_file.put(file_handele,'total roecord' ||'|'|| i);
14
15 utl_file.fclose(file_handele);
16 end;
17 /
PL/SQL procedure successfully completed.
The result:
SQL> $type c:\temp\test.txt
ACCOUNTING
RESEARCH
SALES
OPERATIONS
total roecord|4 --> here's the total number of lines written into the file
SQL>

Function in PL SQL (Oracle) Error

CREATE OR REPLACE FUNCTION ComputeFreight(subtotal NUMBER)
RETURN NUMBER
IS
freightCharge NUMBER;
BEGIN
IF subtotal <= 15000 THEN
freightCharge := (subtotal * .10);
ELSIF subtotal > 15000 THEN
freightCharge := (subtotal * .15);
RETURN(freightCharge);
END IF;
END;
DECLARE
subtotal NUMBER := 15000;
BEGIN
DBMS_OUTPUT.PUT_LINE( ComputeFreight(subtotal) );
END;
I don't know whats wrong with my code but it always shows this error:
Invalid statement
Invalid statement
ORA-06503: PL/SQL: Function returned without value ORA-06512: at
"SQL_JQQXUMCMKFMRHRPZCYFNBEVTN.COMPUTEFREIGHT", line 12 ORA-06512: at
line 4 ORA-06512: at "SYS.DBMS_SQL", line 1721
The return statement should be outside the if-else:
CREATE OR REPLACE FUNCTION ComputeFreight(subtotal NUMBER)
RETURN NUMBER
IS
freightCharge NUMBER;
BEGIN
IF subtotal <= 15000 THEN
freightCharge := (subtotal * .10);
ELSIF subtotal > 15000 THEN
freightCharge := (subtotal * .15);
END IF;
RETURN(freightCharge); -- here
END;
If this is practice for the IF statement, that's fine (with GurV's suggested placement of the RETURN statement). However, if you actually need this in some sort of production, you may want to simplify the function and make it more efficient. Something like this:
CREATE OR REPLACE FUNCTION ComputeFreight(subtotal NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN subtotal * (CASE WHEN subtotal <= 15000 THEN 0.1 ELSE 0.15 END);
END;

oracle pl/sql ora-01722 error

I have a simple oracle statement in my procedure:
update org.security_training_question a
set a.actv_indr = 'N' where a.qstn_id in (v_qstns_to_delete);
v_qstns_to_delete is a parameter being passed. It is a varchar2 field and a.qstn_id is a numeric field.
When calling the Stored Procedure, for v_qstns_to_delete I am passing the following String: "24, 43, 23, 44, 21".
When I run the statement output the stored procedure thenn it runs fine but when I run it as a stored procedure I get an error on the above line saying Invalid Number.
Any clue?
You can't use a "in" clause with a variable like that. One way around it is
declare stmt varchar2(4000);
begin
stmt := 'update org.security_training_question a set a.actv_indr = ''N'' where a.qstn_id in ('||v_qstns_to_delete||')';
execute immediate stmt;
end;
if v_qstns_to_delete is a varchar, you would need to convert it somewhat to let Oracle understand that there may be several items in it. One method would be to convert the string to a table of items.
Supposing qstn_id is a NUMBER column, you would:
SQL> CREATE TYPE tab_number AS TABLE OF NUMBER;
2 /
Type created
SQL> CREATE OR REPLACE FUNCTION to_tab_number(p_in VARCHAR2,
2 p_separator VARCHAR2 DEFAULT ',')
3 RETURN tab_number AS
4 l_result tab_number := tab_number();
5 l_tail LONG := p_in;
6 BEGIN
7 WHILE l_tail IS NOT NULL LOOP
8 l_result.EXTEND;
9 IF instr(l_tail, p_separator) != 0 THEN
10 l_result(l_result.COUNT) := to_number(substr(l_tail,
11 1,
12 instr(l_tail, p_separator) - 1));
13 l_tail := substr(l_tail, instr(l_tail, p_separator) + 1);
14 ELSE
15 l_result(l_result.COUNT) := to_number(l_tail);
16 l_tail := NULL;
17 END IF;
18 END LOOP;
19 RETURN l_result;
20 END;
21 /
Function created
You could then convert a string to a table of number from SQL:
SQL> SELECT * FROM TABLE(to_tab_number('24, 43, 23, 44, 21'));
COLUMN_VALUE
------------
24
43
23
44
21
To do a variable in-list:
SQL> SELECT object_id, owner
2 FROM all_objects
3 WHERE object_id IN (SELECT column_value FROM TABLE(to_tab_number('18,19,20')));
OBJECT_ID OWNER
---------- ------------------------------
18 SYS
19 SYS
20 SYS
More on the same subject on askTom.