How do I use 'if' condition inside a 'if' condition? - oracle

I am trying to use 'if' condition inside a 'if' condition to create a function.
I know the syntax looks somewhat like below, but I am unable to do it in my code.
IF sales > (quota + 200) THEN
bonus := (sales - quota)/4;
ELSE
IF sales > quota THEN
bonus := 50;
ELSE
bonus := 0;
END IF;
END IF;
Below is the program I am trying to complete. Please help me with it.
Its a function to find phone bill amount wrt given number of calls
and plan Type
CREATE OR REPLACE FUNCTION BILL(NUM_OF_CALLS NUMBER, PLAN_TYPE NUMBER) RETURN NUMBER IS :
BILL_AMT NUMBER;
MIN_1 NUMBER :=150;
MIN_2 NUMBER :=1000;
BEGIN
IF PLAN_TYPE:=150 THEN
IF NUM_OF_CALLS<150 THEN
BILL_AMT:=MIN_1;
ELSIF NUM_OF_CALLS BETWEEN 151 AND 250 THEN
BILL_AMT:=MIN_1+(NUM_OF_CALLS-150);
ELSIF NUM_OF_CALLS BETWEEN 251 AND 400 THEN
BILL_AMT:=MIN_1+(100*1)+(NUM_OF_CALLS-250)*0.5;
ELSIF NUM_OF_CALLS>400 THEN
BILL_AMT:=MIN_1+(100*1)+(150*0.5)+(NUM_OF_CALLS-400)*0.3;
END IF;
ELSE PLAN_TYPE:=500 THEN
IF NUM_OF_CALLS<1000 THEN
BILL_AMT:=MIN_2;
ELSIF NUM_OF_CALLS BETWEEN 1001 AND 1500 THEN
BILL_AMT:=MIN_2+(NUM_OF_CALLS-1000)*0.50;
ELSIF NUM_OF_CALLS>1500 THEN
BILL_AMT:=MIN_2+(500*0.50)+(NUM_OF_CALLS-1500)*0.25;
END IF;
END IF;
RETURN BILL_AMT;
END;
Below are the errors
SQL> show error
Errors for FUNCTION BILL:
LINE/COL ERROR
11/14 PLS-00103: Encountered the symbol "=" when expecting one of the
following:
. ( * # % & = - + < / > at in is mod remainder not rem then
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
The symbol "* was inserted before "=" to continue.
22/22 PLS-00103: Encountered the symbol "THEN" when expecting one of
the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
31/6 PLS-00103: Encountered the symbol "IF" when expecting one of the
following:
; <an identifier> <a double-quoted delimited-identifier>
current delete exists prior <a single-quoted SQL string>

Your answer is directly in the error output.
PLSQL uses := for assignation and = for comparison. You are intermixing these operators and causing these errors.
Read the errors closely, they exactly describe the problem.
Hint: Add small amounts of logic at a time so that you know where your problems originate. Each of us learns this at some point in time :)

Something like this should work for you:
CREATE OR REPLACE
FUNCTION BILL(NUM_OF_CALLS NUMBER, PLAN_TYPE NUMBER)
RETURN NUMBER
IS
BILL_AMT NUMBER;
MIN_1 NUMBER := 150;
MIN_2 NUMBER := 1000;
BEGIN
IF PLAN_TYPE = 150
THEN
IF NUM_OF_CALLS<150
THEN
BILL_AMT:= MIN_1;
ELSIF NUM_OF_CALLS BETWEEN 151 AND 250
THEN
BILL_AMT:=MIN_1+(NUM_OF_CALLS-150);
ELSIF NUM_OF_CALLS BETWEEN 251 AND 400
THEN
BILL_AMT:=MIN_1+(100*1)+(NUM_OF_CALLS-250)*0.5;
ELSIF NUM_OF_CALLS>400
THEN
BILL_AMT:=MIN_1+(100*1)+(150*0.5)+(NUM_OF_CALLS-400)*0.3;
END IF;
ELSIF PLAN_TYPE = 500
THEN
IF NUM_OF_CALLS<1000
THEN
BILL_AMT:=MIN_2;
ELSIF NUM_OF_CALLS BETWEEN 1001 AND 1500 THEN
BILL_AMT:=MIN_2+(NUM_OF_CALLS-1000)*0.50;
ELSIF NUM_OF_CALLS>1500 THEN
BILL_AMT:=MIN_2+(500*0.50)+(NUM_OF_CALLS-1500)*0.25;
END IF;
END IF;
RETURN BILL_AMT;
END BILL;
Hope it helps...

You can't
ELSE PLAN_TYPE:=500 THEN
But you can
ELSIF PLAN_TYPE =500 THEN
If I've got your logic flow figured out
CREATE OR REPLACE FUNCTION BILL(NUM_OF_CALLS NUMBER, PLAN_TYPE NUMBER) RETURN NUMBER IS
BILL_AMT NUMBER;
MIN_1 NUMBER :=150;
MIN_2 NUMBER :=1000;
BEGIN
IF PLAN_TYPE = 150
THEN
IF NUM_OF_CALLS<150 THEN
BILL_AMT :=MIN_1;
ELSIF NUM_OF_CALLS BETWEEN 151 AND 250 THEN
BILL_AMT:=MIN_1+(NUM_OF_CALLS-150);
ELSIF NUM_OF_CALLS BETWEEN 251 AND 400 THEN
BILL_AMT:=MIN_1+(100*1)+(NUM_OF_CALLS-250)*0.5;
ELSIF NUM_OF_CALLS>400 THEN
BILL_AMT:=MIN_1+(100*1)+(150*0.5)+(NUM_OF_CALLS-400)*0.3;
END IF;
ELSIF PLAN_TYPE = 500 THEN
IF NUM_OF_CALLS<1000 THEN
BILL_AMT:=MIN_2;
ELSIF NUM_OF_CALLS BETWEEN 1001 AND 1500 THEN
BILL_AMT:=MIN_2+(NUM_OF_CALLS-1000)*0.50;
ELSIF NUM_OF_CALLS>1500 THEN
BILL_AMT:=MIN_2+(500*0.50)+(NUM_OF_CALLS-1500)*0.25;
END IF;
END IF;
RETURN BILL_AMT;
END;

Related

How to return two types in pl/sql oracle

How to return two types in pl/sql oracle?
return number -- here I tell than function reurns number, but i want to return number and string when an exception is thrown
is
prPrice number; -- product price
curFrom number; -- price
pgcount number := 0; -- product count
noProductsOnDate EXCEPTION;
wrongCurrency EXCEPTION;
begin
SELECT COUNT(*) INTO pgcount
from Products pr, Outgoing outg, Incoming inc
where pr.PROD_ID = outg.PROD_ID and pr.PROD_ID = inc.PROD_ID and inc.inc_date > d
Having sum(inc.quantity) > sum(outg.quantity);
if pgcount = 0 or pgcount is null then
raise noProductsOnDate;
END IF;
if curTo > 2 OR curTo < 1 then
raise wrongCurrency;
end if;
If curTo = 1
then curFrom := 2;
Elsif curTo = 2
then curFrom := 1;
END IF;
select pric.Value*cour.value into prPrice from Prices pric, Cources cour
where p = pric.prod_id and pric.DAYFROM <= d and (pric.DAYTO >= d or pric.DAYTO is null) and cour.cur_idto = curTo and cour.cur_idfrom = curFrom;
return prPrice; -- here i wanna return number
exception
when noProductsOnDate then return '1q'; -- here i wanna return string (error message)
when wrongCurrency then return '2q'; -- here i wanna return string (error message)
end;
I can't return string in exception, because function return number
Maybe I doing something wrong,
Please, tell me how can I return several data types from one function, maybe I should do everything differently, but I don't understand how to do it ((
You can't do it that way, but can another way around - declare function to return varchar2. Then, in your code, you can
create function ...
return varchar2
is
begin
... do whatever you're doing
return to_char(poPrice);
exception
when ... then return '1q';
end;
I write my functions often in this form:
return 0 in case of success
return a positive number in case of a warning (often not used)
return a negative number in case of an error
And I use out parameters for the function results, in your case the price and/or a message.
Something along the lines of:
CREATE OR REPLACE FUNCTION my_function(vi_date IN DATE,
vo_price OUT NUMBER,
vo_msg OUT VARCHAR) RETURN INTEGER IS
BEGIN
...
IF pgcount = 0 OR pgcount IS NULL THEN
vo_msg := 'No products on that date.';
RETURN -20001; -- return custom error code
END IF;
...
IF vo_price < 0 THEN
vo_msg := 'Price is negative. Calculation my be wrong.';
RETURN 1; -- return warning flag (positive number)
ELSE
RETURN 0; -- means success
END IF;
EXCEPTION WHEN OTHERS THEN
-- Error. Return negative number. SQLCODE is always the negative ORA code
-- except for ORA-1403 which is strangely SQLCODE 100 instead
vo_msg := SQLERRM;
RETURN CASE WHEN SQLCODE = 100 THEN -1403 ELSE SQLCODE END;
END my_function;
Then call it like this:
DECLARE
v_code INTEGER;
v_price NUMBER (10,2);
v_msg VARCHAR(1000);
BEGIN
v_code := my_function(DATE '2022-09-29', v_price, v_msg);
IF v_code >= 0 THEN
DBMS_OUTPUT.PUT_LINE('The price is: ' || v_price);
END IF;
IF v_code <> 0 THEN
DBMS_OUTPUT.PUT_LINE('Message: ' || v_msg);
END IF;
END;

If statement inside Trigger not working SQL(Oracle)

My goal is to create a trigger that checks if the number you are trying to enter NR_RECIBO is in the table Doc_cabecalho with the attribute TIPO_DOC = 4
CREATE OR REPLACE TRIGGER ValidaRecibo
BEFORE INSERT ON Recibo
FOR EACH ROW
DECLARE val NUMBER;
BEGIN
SELECT COUNT(*) INTO val
FROM Doc_cabecalho
WHERE (TIPO_DOC = 4 AND NR_DOCUMENTO = :NEW.NR_RECIBO);
IF val = 0
THEN (-20502, ' Only from department 4 ');
END IF;
END ValidaRecibo;
Yet, this raises the following error:
PLS-00103: Encountered the symbol "," when expecting one of the following:
* & = - + < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec as between || member submultiset
IF val = 0 THEN
raise_application_error(-20502, ' Only from department 6 ');
And you should decide between DOC_TIPO and TIPO_DOC ;)

Error when creating Elsif Trigger Before Update

I am creating trigger when Selisih column is equal to 0, then Status column become 'Partial'. If QtyInternalUse column is equal to QtyRequested, then Status column is Completed, else, it is Not Issued
CREATE OR REPLACE TRIGGER TG_STATUSINREQ
BEFORE UPDATE OR INSERT ON M_INTERNALREQUESTERLINE
FOR EACH ROW
BEGIN
IF (:new.Selisih <> 0 ) THEN
:new.Status := 'Partial';
ELSIF :new.QtyInternalUse := :new.QtyRequested THEN
:new.Status := 'Completed';
ELSE
:new.Status := 'Not Issued';
END IF;
END;
I've tried execute it and there's error that says
PLS-00103: Encountered the symbol "=" when expecting one of the
following:
. ( * # % & = - + < / > at in is mod remainder not rem then
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator multiset member submultiset
The symbol "* was inserted before "=" to continue.
I've tried deleting : in = but still it won't work. How can I fix this?
REVISION
I have updated the logic and the := . The trigger was created and it's like this :
BEGIN
IF (:new.QtyInternalUse = 0 ) THEN
:new.Status := 'Not Issued';
ELSIF :new.QtyInternalUse = :new.QtyRequested THEN
:new.Status := 'Completed';
ELSE
:new.Status := 'Partial';
END IF;
END;
This should be pretty easy google-resolve. Still here you go.
ELSIF :new.QtyInternalUse := :new.QtyRequested THEN
You are trying to compare but using assignment operator[:=]. Use equals[=] in stead that will resolve your problem.
ELSIF :new.QtyInternalUse = :new.QtyRequested THEN

Oracle Database PLSQL Error: PLS-00103

I'm writing simple function in Oracle Database 11g that count summary salary for employee. For this we need to count days with specific status. Days is present as fields in table (Day_1, Day_2, ..., Day_30).
But i have got error during compilation:
Error(50,9): PLS-00103: Encountered the symbol ";" when expecting one of the following: :=.(#%;
Code of my package (a place where there is an error marked in code of function f2):
CREATE OR REPLACE PACKAGE pack IS
FUNCTION f1 (id IN NUMBER) return t2 PIPELINED;
FUNCTION f2 (id IN NUMBER) return number;
end pack;
/
CREATE OR REPLACE PACKAGE BODY pack IS
FUNCTION f1 (id IN NUMBER) return t2 PIPELINED IS
name VARCHAR2(50);
num number;
BEGIN
FOR i IN 1 .. id LOOP
SELECT отдел
into name
from отдел
where ид_отдела = i;
select sum(КОЛИЧЕСТВО)
into num
from Таблица_3
join Таблица_2
on Таблица_3.КТО_ПРОДАЛ = Таблица_2.ЧЛВК_ИД
where отдел = i;
PIPE ROW( t1(i, name, num) );
END LOOP;
RETURN;
END f1;
FUNCTION f2 (id IN NUMBER) return NUMBER AS
WorkingDays NUMBER := 0;
CurrentDay VARCHAR2(50);
Salary NUMBER := 120;
Total NUMBER := 0;
BEGIN
FOR i IN 1 .. 30 LOOP
EXECUTE IMMEDIATE 'SELECT День_' || i || ' FROM Таблица_2 WHERE ЧЛВК_ИД = id INTO CurrentDay';
IF WorkingDays IN ('КОМАНДИРОВКА','ВЫХОДНОЙ','ПРАЗДНИК') THEN -- <--- Here
WorkingDays := WorkingDays + 1;
END IF;
END LOOP;
Total : = Salary * WorkingDays;
RETURN Total;
END f2;
end pack;
/
How can i solve this? Maybe the problem is in the logic of the program?
That is an error on parsing, and be aware that it often does not accurately show the error itself, but where the next symbol error occurred. For example:
declare
x number;
y number;
begin
if x = 1 then
y := 1 --I forget to put on the semi-colon to end the line
end if;
end;
You'd expect an error on the missing semi-colon. What you get is:
ORA-06550: line 7, column 2:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
The symbol ";" was substituted for "END" to continue.
Since in your comments you talk about changing things - perhaps to make it more readable for us (and thank you!), it may be obscuring the actual syntax glitch.
Two things I notice:
Total : = Salary * WorkingDays;
That has a space between the : and = that shouldn't be there
and:
FUNCTION f2 (id IN NUMBER) return NUMBER AS
which is normally
FUNCTION f2 (id IN NUMBER) return NUMBER IS

PLS-00103 when trying to call a procedure

When attempting to compile I am getting the following errors
Error(16,8): PLS-00103: Encountered the symbol "SPROLLUPEXPENSEITEM"
when expecting one of the following: := . ( # % ; The symbol ":="
was substituted for "SPROLLUPEXPENSEITEM" to continue.
and
Error(17,15): PLS-00103: Encountered the symbol "=" when expecting one
of the following: . ( * # % & = - + < / > at in is mod remainder
not rem then <> or != or ~= >= <= <> and or like
like2 like4 likec between || multiset member submultiset
create or replace
TRIGGER tr_ExpenseItem_Rollup
AFTER DELETE OR UPDATE of ExpApprAmt
ON ExpenseItem
FOR EACH ROW
DECLARE
RollupAmt Number;
BlnResult Boolean;
BEGIN
IF DELETING THEN
RollupAmt := -1 * :Old.ExpApprAmt;
End If;
IF UPDATING Then
RollupAmt := :New.ExpApprAmt - :Old.ExpApprAmt;
End IF;
Call spRollUpExpenseItem(:New.ERNo,:New.ECNo,RollupAmt,BlnResult);
If BlnResult := TRUE
--Additional Logic Here
End IF;
END;
I'm a student and very new at this, so any help would be appreciated.
call isn't a keyword in PL/SQL and to run a stored procedure you just use its name. Remove call from before spRollUpExpenseItem:
create or replace
TRIGGER tr_ExpenseItem_Rollup
AFTER DELETE OR UPDATE of ExpApprAmt
ON ExpenseItem
FOR EACH ROW
DECLARE
RollupAmt Number;
BlnResult Boolean;
BEGIN
IF DELETING THEN
RollupAmt := -1 * :Old.ExpApprAmt;
End If;
IF UPDATING Then
RollupAmt := :New.ExpApprAmt - :Old.ExpApprAmt;
End IF;
spRollUpExpenseItem(:New.ERNo,:New.ECNo,RollupAmt,BlnResult);
If BlnResult = TRUE Then
--Additional Logic Here
End IF;
END;
I believe your problem is in the last if statement. You're missing Then and you're using := which is the assignment operator, you should use = instead.
If BlnResult = TRUE Then
or just
If BlnResult Then

Resources