Printing odd and even numbers in pl/sql - sql

I'm new to programming; I want to print odd and even number inside a loop the problem that the if does not work and it will always print else no matter the number you have entered:
DECLARE
x NUMBER:=:x;
r NUMBER:=:r;
BEGIN
LOOP
if x/2=0 AND r/2!=0 then
dbms_output.put_line('Even number x='||x);
dbms_output.put_line('Odd number r='||r);
x:= x+2;
r:= r+2;
else
dbms_output.put_line('Odd number x='||x);
dbms_output.put_line('Even number r='||r);
x:=x+2;
r:=r+2;
exit when x>20 and r>20;
end if;
end loop;
end;

Instead of x/2=0 you need to use mod(x,2)=0 to check whether it's even number or not. I have separated the condition for x and r. Check out below code:
DECLARE
x NUMBER:=2;
r NUMBER:=3;
BEGIN
LOOP
if mod(x,2)=0 then
dbms_output.put_line('Even number x='||x);
else
dbms_output.put_line('Odd number x='||x);
end if;
if mod(r,2)=0 then
dbms_output.put_line('Even number r='||r);
else
dbms_output.put_line('Odd number r='||r);
end if;
x:= x+2;
r:= r+2;
exit when x>20 and r>20;
end loop;
end;

Related

Toad oracle 10.5 [duplicate]

I have this anonymous PL/SQL block which calculates and prints a value return from a table.
DECLARE
U_ID NUMBER :=39;
RETAIL BINARY_FLOAT:=1;
FLAG NUMBER;
BEGIN
SELECT NVL(RETAIL_AMOUNT,1),UNIT_ID INTO RETAIL, FLAG FROM UNITS WHERE UNIT_ID=U_ID;
LOOP
SELECT NVL(MAX(UNIT_ID),U_ID) INTO FLAG FROM UNITS WHERE FATHER_ID=FLAG;
IF FLAG=U_ID THEN EXIT; END IF;
SELECT RETAIL* RETAIL_AMOUNT INTO RETAIL FROM UNITS WHERE UNIT_ID=FLAG;
EXIT WHEN FLAG=U_ID;
END LOOP;
DBMS_OUTPUT.PUT_LINE( RETAIL);
END;
This block work correctly, but I wanted to do the same thing using a PL/SQL Function
I wrote the function as follow:
CREATE OR REPLACE FUNCTION GET_UNIT_RETAIL(U_ID NUMBER)
RETURN NUMBER
IS
RETAIL BINARY_FLOAT:=1;
FLAG NUMBER;
BEGIN
SELECT NVL(RETAIL_AMOUNT,1),UNIT_ID
INTO RETAIL, FLAG
FROM UNITS
WHERE UNIT_ID=U_ID;
LOOP
SELECT NVL(MAX(UNIT_ID),U_ID)
INTO FLAG
FROM UNITS
WHERE FATHER_ID=FLAG;
IF FLAG=U_ID THEN
EXIT;
END IF;
SELECT RETAIL* RETAIL_AMOUNT
INTO RETAIL
FROM UNITS
WHERE UNIT_ID=FLAG;
EXIT WHEN FLAG=U_ID;
END LOOP;
RETURN NUMBER;
END;
/
When I try to execute the above code to save the function to the database, the environment (SQL*PLUS) hangs for a long time and at the end returns this error:
ERROR at line 1:
ORA-04021: timeout occurred while waiting to lock object
What is the problem ??? Please !
Sounds like ddl_lock problem
Take a look at
dba_ddl_locks to see who is "blocking" a create or replace.
Also try to create under different name - and see what happens.
The problem was because the Object GET_UNIT_RETAIL was busy by other environment
Here is the answer:
https://community.oracle.com/thread/2321256

Error while writing to array plsql how to fix? Extend doesn't work also

so I am trying to write to an array in PL/SQL, and I always get the subscript outside of limit error. I've seen similar posts and implemented everything based on those answers, I can't seem to find what I'm doing wrong. The line giving the error is "arr_quartosLivres(counter) := q.id;" I've tried to extend the array and it still doesn't work, however, either way, the look only runs 21 times (because there are only 21 values in the table quarto) so it shouldn't even need to be extended. Any help would be highly appreciated! Thank you
SET SERVEROUTPUT ON;
DECLARE
p_idReserva reserva.id%type := 408;
v_dataEntradaReserva reserva.data_entrada%type;
counter integer := 0;
type arr_aux IS varray(21) of quarto.id%type;
arr_quartosLivres arr_aux := arr_aux();
BEGIN
SELECT data_entrada INTO v_dataEntradaReserva FROM reserva WHERE id = p_idreserva;
FOR q IN (SELECT * FROM quarto)
LOOP
BEGIN
IF isQuartoIndisponivel(q.id, v_dataEntradaReserva)
THEN DBMS_OUTPUT.PUT_LINE('nao disponivel' || counter);
arr_quartosLivres(counter) := q.id;
ELSE DBMS_OUTPUT.PUT_LINE('disponivel' || counter);
END IF;
counter := counter + 1;
END;
END LOOP;
END;
The index values for varray begin with 1. Your logic is trying to use index value 0. Thus index out of range. BTW extend does not apply to varray, when declared a varray has a fixed size. You have 3 solutions: initialize counter to 1 instead of 0, or move incrementing it prior to its use as an index. Since as it stands you increment every time through the loop, even when the IF condition returns false and you do not use the counter as an index, leaving a NULL value in the array.But you use counter for 2 different purposes: Counting rows processed and index into the array. Since the row value may not be put into the array then your 3rd option is to introduce another variable for the index. Further there is no need for the BEGIN ... End block in the loop.
declare
p_idreserva reserva.id%type := 408;
v_dataentradareserva reserva.data_entrada%type;
counter integer := 0;
type arr_aux is varray(21) of quarto.id%type;
arr_quartoslivres arr_aux := arr_aux();
varray_index integer := 1 ; -- index varaibal for varray.
begin
select data_entrada into v_dataentradareserva from reserva where id = p_idreserva;
for q in (select * from quarto)
loop
if isquartoindisponivel(q.id, v_dataentradareserva)
then
dbms_output.put_line('nao disponivel' || counter || ' at index ' || varray_index);
arr_quartoslivres(varray_index) := q.id;
varray_index := varray_index + 1;
else
dbms_output.put_line('disponivel' || counter);
end if;
counter := counter + 1;
end loop;
end;

While Loop and If/Else in PL/SQL

I am trying to write a procedure that will produce the following output
exec WinOrLose(4)
Welcome to the Win or Lose Game. Your number is 4.
You win.
You lose.
You win.
You lose.
==> You lose!
So far I have this:
CREATE or REPLACE Procedure WinOrLose (
p_choice number ) AS
v_answer number;
DECLARE
v_answer := p_choice
BEGIN
dbms_output.put_line ('Welcome to the Win or Lose Game. Your number is ' ||
v_answer);
FOR v_answer in 1..10
IF MOD(v_answer, 2) = 0 THEN -- v_answer is even
dbms_output.put_line (You lose)
END;
/
I'm unsure of where to go from there. My thought process (psuedocode) is this:
SET v_answer := 1
While Loop (outside)
MOD(v_answer,2) = 0 then dbms.output (YOU LOSE)
ELSE
dbms.output (YOU WIN)
end if;
v_answer := p_choice
CREATE or REPLACE Procedure WinOrLose (
p_choice number ) AS
BEGIN
dbms_output.put_line ('Welcome to the Win or Lose Game. Your number is ' ||
p_choice);
FOR v_counter in 1..p_choice LOOP
IF (MOD(v_counter, 2) = 0)
THEN
dbms_output.put_line ('You win');
ELSE
dbms_output.put_line ('You lose');
END IF;
END LOOP;
IF (MOD(p_choice , 2) = 0)
THEN
dbms_output.put_line ('==> You win!');
ELSE
dbms_output.put_line ('==> You lose!');
END IF;
END;
/

What is << some text >> in oracle

I found this character while reading some blog of pl sql << some text >> .
I found this character from following blog http://www.oracle-base.com/articles/8i/collections-8i.php
As others have said, <<some_text>> is a label named "some_text". Labels aren't often used in PL/SQL but can be helpful in a variety of contexts.
As an example, let's say you have several nested loops, execution has reached the very inner-most level, and the code needs to exit from all the nested loops and continue after the outer-most one. Here a label can be used in the following fashion:
<<outer_most_loop>>
LOOP
...
<<next_inner_loop>>
LOOP
...
<<inner_most_loop>>
LOOP
...
IF something <> something_else THEN
EXIT outer_most_loop;
END IF;
...
END LOOP inner_most_loop;
...
END LOOP next_inner_loop;
...
END LOOP outer_most_loop;
-- Execution continues here after EXIT outer_most_loop;
something := something_else;
...
Next, let's say that you've got some code with nested blocks, each of which declares a variable of the same name, so that you need to instruct the compiler about which of the same-named variables you intend to use. In this case you could use a label like this:
<<outer>>
DECLARE
nNumber NUMBER := 1;
BEGIN
<<inner>>
DECLARE
nNumber NUMBER := 2;
BEGIN
DBMS_OUTPUT.PUT_LINE('outer.nNumber=' || outer.nNumber);
DBMS_OUTPUT.PUT_LINE('inner.nNumber=' || inner.nNumber);
END inner;
END outer;
Labels can also be useful if you insist on giving a variable the same name as a column in a table. As an example, let's say that you have a table named PEOPLE with a non-nullable column named LASTNAME and you want to delete everyone with LASTNAME = 'JARVIS'. The following code:
DECLARE
lastname VARCHAR2(100) := 'JARVIS';
BEGIN
DELETE FROM PEOPLE
WHERE LASTNAME = lastname;
END;
will not do what you intended - instead, it will delete every row in the PEOPLE table. This occurs because in the case of potentially ambiguous names, PL/SQL will choose to use the column in the table instead of the local variable or parameter; thus, the above is interpreted as
DECLARE
lastname VARCHAR2(100) := 'JARVIS';
BEGIN
DELETE FROM PEOPLE p
WHERE p.LASTNAME = p.lastname;
END;
and boom! Every row in the table goes bye-bye. :-) A label can be used to qualify the variable name as follows:
<<outer>>
DECLARE
lastname VARCHAR2(100) := 'JARVIS';
BEGIN
DELETE FROM PEOPLE p
WHERE p.LASTNAME = outer.lastname;
END;
Execute this and only those people with LASTNAME = 'JARVIS' will vanish.
And yes - as someone else said, you can GOTO a label:
FUNCTION SOME_FUNC RETURN NUMBER
IS
SOMETHING NUMBER := 1;
SOMETHING_ELSE NUMBER := 42;
BEGIN
IF SOMETHING <> SOMETHING_ELSE THEN
GOTO HECK;
END IF;
RETURN 0;
<<HECK>>
RETURN -1;
END;
(Ewwwww! Code like that just feels so wrong..!)
Share and enjoy.
It's often used to label loops, cursors, etc.
You can use that label in goto statements. Else, it is just 'comment'.
Sample from Oracle:
DECLARE
p VARCHAR2(30);
n PLS_INTEGER := 37; -- test any integer > 2 for prime
BEGIN
FOR j in 2..ROUND(SQRT(n)) LOOP
IF n MOD j = 0 THEN -- test for prime
p := ' is not a prime number'; -- not a prime number
GOTO print_now; -- << here is the GOTO
END IF;
END LOOP;
p := ' is a prime number';
<<print_now>> -- << and it executes this
DBMS_OUTPUT.PUT_LINE(TO_CHAR(n) || p);
END;
/
It is a label, a subgroup of comments in the plsql syntax.
http://ss64.com/oraplsql/operators.html
Its is a label delimeter
<< label delimiter (begin)
label delimiter (end) >>
http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/02_funds.htm

Cursor error in SQL

I'm trying to implement a cursor, & after solving many errors I've finally come to a point where it runs, but it goes into infinite loop...
I've put the image of table below as image.
Aim of cursor: to calculate bowling average & store in 'bowling_avg' column.
here's the cursor code :
DECLARE
CURSOR BOWL_AVG IS SELECT SID,MATCHES,BOWLING_AVG,WICKETS
FROM BOWLING_STATS ;
NSID BOWLING_STATS.SID%TYPE;
NMATCHES BOWLING_STATS.MATCHES%TYPE;
NBOWLING_AVG BOWLING_STATS.BOWLING_AVG%TYPE;
NWICKETS BOWLING_STATS.WICKETS%TYPE;
BEGIN
OPEN BOWL_AVG;
IF BOWL_AVG%ISOPEN THEN
LOOP
FETCH BOWL_AVG INTO NSID,NMATCHES,NBOWLING_AVG,NWICKETS;
EXIT WHEN BOWL_AVG%NOTFOUND;
IF BOWL_AVG%FOUND THEN
LOOP
UPDATE BOWLING_STATS SET BOWLING_AVG=NWICKETS/NMATCHES WHERE SID=NSID ;
EXIT WHEN BOWL_AVG%NOTFOUND;
END LOOP;
END IF;
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('UNABLE TO OPEN CURSOR');
END IF;
CLOSE BOWL_AVG;
END;
I'm running this in oracle database 10g.
I ask for assistance in finding the error.
Thanks in advance.
Adding whitespace to your code makes it clearer what you're doing:
declare
cursor bowl_avg is
select sid, matches, bowling_avg, wickets
from bowling_stats;
nsid bowling_stats.sid%type;
nmatches bowling_stats.matches%type;
nbowling_avg bowling_stats.bowling_avg%type;
nwickets bowling_stats.wickets%type;
begin
-- 1. Open Cursor
open bowl_avg;
-- 2. Check if Cursor is open
if bowl_avg%isopen then
-- 3. Loop
loop
-- 4. Get record
fetch bowl_avg into nsid, nmatches, nbowling_avg, nwickets;
-- 5. Exit if no records left
exit when bowl_avg%notfound;
-- 6. If there is a record
if bowl_avg%found then
-- 7. Loop
loop
update bowling_stats
set bowling_avg = nwickets / nmatches
where sid = nsid;
-- 8. Exit if there is no record.
exit when bowl_avg%notfound;
end loop;
end if;
end loop;
else
dbms_output.put_line('unable to open cursor');
end if;
close bowl_avg;
end;
/
There are a number of contradictions in there.
In 1 and 2 you're opening a cursor and then checking if there is an open cursor. A error will be raised if the cursor didn't open so you can ignore this step.
In 5 and 6 you exit if you can't fetch a new record then check if you have a record. This is a contradiction so stage 6 will (almost) always evaluate to true.
in 7 and 8 you loop, exiting when you don't have a record. As you've just checked (twice) that you do in fact have a record you'll never exit this loop.
If you insist on doing this with cursors then you can remove most of your code and it should work fine:
declare
cursor bowl_avg is
select sid, matches, bowling_avg, wickets
from bowling_stats;
nsid bowling_stats.sid%type;
nmatches bowling_stats.matches%type;
nbowling_avg bowling_stats.bowling_avg%type;
nwickets bowling_stats.wickets%type;
begin
-- 1. Open Cursor
open bowl_avg;
-- 2. Loop
loop
-- 3. Get record
fetch bowl_avg into nsid, nmatches, nbowling_avg, nwickets;
-- 4. Exit loop if there is no record.
exit when bowl_avg%notfound;
-- 5. Perform UPDATE statement.
update bowling_stats
set bowling_avg = nwickets / nmatches
where sid = nsid;
end loop;
close bowl_avg;
end;
/
As always a single UPDATE statement without using loops, cursors or PL/SQL will be significantly more effective.