compilation error with oracle statement - oracle

I have the following oracle statement which is giving compilation errors.
v_percent_deceased_households := CASE
WHEN NVL(v_total_households, 0) > 0 THEN
(CAST(NVL(v_deceased_households_count, 0) AS FLOAT(53))
/
CAST(NVL(v_total_households, 0) AS FLOAT(53))) * 100
ELSE 0
END;
Errors are:
Error:
PLS-00103: Encountered the symbol "(" when expecting one of the following:. ) # %
The symbol ")" was substituted for "(" to continue.
Line: 317
Text: (CAST(NVL(v_deceased_households_count, 0) AS FLOAT(53)) / CAST(NVL(v_total_households, 0) AS FLOAT(53))) * 100
Error: PLS-00103: Encountered the symbol "(" when expecting one of the following:. ) # %
Line: 317
Text: (CAST(NVL(v_deceased_households_count, 0) AS FLOAT(53)) / CAST(NVL(v_total_households, 0) AS FLOAT(53))) * 100
I cant seem to resolve this syntax error..

Why the CAST (... AS FLOAT(53))? Why not just:
v_percent_deceased_households := CASE
WHEN v_total_households > 0 THEN
(NVL(v_deceased_households_count, 0) / v_total_households) * 100
ELSE 0
END;
(I removed some redundant NVLs too).

I believe CAST has to be used in a select or 'select into'
For example
select cast( '22-Aug-2003' AS varchar2(30) )
from dual;
or
select cast( v_deceased_households_count AS float ) into myfloat
from dual;

Related

PLS-00103: Encountered the symbol "TO" when expecting one of the following:

LINE/COL ERROR
369/42 PLS-00103: Encountered the symbol "TO" when expecting one of the
following:
( - + case mod new null
continue avg count current max min prior sql stddev sum
variance execute forall merge time timestamp interval date
pipe
<an alternatively-quoted SQ
I am getting this error in this part of code:
if year_float_minutes > (eligible_minutes * 3) then
record_error(end_date, header_id, 0, rule_set, 'ABCDE',
'[year]=' || to c.labor_date_year);
l_rpt := 1;
end if;

Why does the dynamic sql statement erroring

I am trying to run the Dynamic SQL Query and get the output in the cursor. How to rewrite this statement?
OPEN ecur_SS FOR
EXECUTE IMMEDIATE 'select sSQLQUERY FROM DUAL';
END;
sSQLQUERY has my select statement.
sSQL := 'SELECT * from forms' ;
ecur_SS is out sys_refcursor
I am getting the following error:
Error: PLS-00103: Encountered the symbol "IMMEDIATE" when expecting
one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem
<> or != or ~= >= <= <> and or like like2
like4 likec between using || multiset member submultiset The symbol "* was inserted before "IMMEDIATE" to continue.

Error(31,64): PLS-00103: Encountered the symbol "(" when expecting one of the following

I have below function in oracle,
create or replace FUNCTION CALINTEREST
( DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER IS
AInterest NUMERIC(17,8):=0;
PDue NUMERIC(11,2);
IDue NUMERIC(17,8);
INTRate NUMERIC(5,2);
IntDate DATE;
IntDATEDIFF NUMERIC(6):=0;
BEGIN
BEGIN
SELECT
DBRD_PRI_DUE,
DBRD_INT_DUE,
DBRD_INT_RATE,
DBRD_INT_DATE INTO
PDue
,IDue
,INTRate
,IntDate
FROM
DBRD
WHERE
DBRNO = DNumber;
IF(INTRate = 999)
THEN
INTRate := IRate;
END IF;
IntDATEDIFF:=Cast((Sysdate-IntDate) AS NUMBER(11,0));
AInterest := IDue + (PDue * INTRate * IntDATEDIFF / 365 / 100);
END;
RETURN AInterest;
END;
I am getting below two error,
Error(31,64): PLS-00103: Encountered the symbol "(" when expecting one of the following: . ) # % The symbol ")" was substituted for "(" to continue.
Error(31,70): 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 between || multiset member submultiset The symbol "(" was substituted for ")" to continue.
Not sure if this will work for you. On my machine the only errors I get on compilation have to do with the table DBRO (because I don't have a table by that name), but that doesn't mean this does the computations you want it to do. Anyway, play with it and write back if you have more questions.
I changed NUMERIC to NUMBER (the correct name of the Oracle data type for numbers), I changed the computation for IntDATEDIFF in a way that will be immediately obvious when you look at it (Trunc changes the time portion of an Oracle DATE to 00:00:00, and taking the arithmetic "minus" between two dates returns the difference as a number of days), and I removed BEGIN and END; for the inner block- there was no need for an inner block.
create or replace FUNCTION CALINTEREST
( DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER IS
AInterest NUMBER(17,8):=0;
PDue NUMBER(11,2);
IDue NUMBER(17,8);
INTRate NUMBER(5,2);
IntDate DATE;
IntDATEDIFF NUMBER(6):=0;
BEGIN
SELECT
DBRD_PRI_DUE,
DBRD_INT_DUE,
DBRD_INT_RATE,
DBRD_INT_DATE INTO
PDue
,IDue
,INTRate
,IntDate
FROM
DBRD
WHERE
DBRNO = DNumber;
IF(INTRate = 999)
THEN
INTRate := IRate;
END IF;
IntDATEDIFF:=trunc(Sysdate) - trunc(IntDate);
AInterest := IDue + (PDue * INTRate * IntDATEDIFF / 365 / 100);
RETURN AInterest;
END;
/
create or replace FUNCTION CALINTEREST(
DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER
IS
PDue NUMERIC(11,2);
IDue NUMERIC(17,8);
INTRate NUMERIC(5,2);
IntDate DATE;
BEGIN
SELECT DBRD_PRI_DUE, DBRD_INT_DUE, DBRD_INT_RATE, DBRD_INT_DATE
INTO PDue, IDue, INTRate, IntDate
FROM DBRD
WHERE DBRNO = DNumber;
IF (INTRate = 999) THEN
INTRate := IRate;
END IF;
RETURN IDue + (PDue * INTRate * TRUNC(SYSDATE - IntDate) / 365 / 100);
END;
/
SHOW ERRORS;
Or moving the logic into SQL:
create or replace FUNCTION CALINTEREST(
DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER
IS
p_interest NUMBER(17,8);
BEGIN
SELECT DBRD_INT_DUE
+ ( DBRD_PRI_DUE
* CASE DBRD_INT_RATE
WHEN 999 THEN IRate
ELSE DBRD_INT_RATE
END
* TRUNC( SYSDATE - DBRD_INT_DATE )
/ 365
/ 100
)
INTO p_interest
FROM DBRD
WHERE DBRNO = DNumber;
RETURN p_interest;
END;
/
SHOW ERRORS;

PLS-00103: Encountered the symbol ";" when expecting one of the following: . ( ) * # % & - + /

Compilation failed, line 10 (14:27:16)
The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PLS-00103: Encountered the symbol ";" when expecting one of the following: . ( ) * # % & - + / at mod remainder rem with and or group having intersect minus start union where connect || multiset
The symbol ";" was ignored.**
create or replace trigger "PROMOS_T2"
BEFORE insert or update on "PROMOS"
for each row
DECLARE
ma_exp1 EXCEPTION;
ma_exp2 EXCEPTION;
ma_exp3 EXCEPTION;
cap LOGTS.CAPACITE%TYPE;
nbr INTEGER;
begin
SELECT COUNT (*) INTO nbr FROM LOGTS WHERE :NEW."IDLOG"=IDLOG;
SELECT CAPACITE INTO cap FROM LOGTS WHERE :NEW."IDLOG"=IDLOG;
if (exists(SELECT * FROM PROMOS WHERE :NEW."IDPROMO"=IDPROMO;) )THEN
RAISE ma_exp1;
elsif nbr=1 AND cap < :NEW."NBPLACES" THEN
RAISE ma_exp2;
else
RAISE ma_exp3;
end if;
EXCEPTION
WHEN ma_exp1 THEN
RAISE_APPLICATION_ERROR(-20004,'la promos dèja existe');
WHEN ma_exp2 THEN
RAISE_APPLICATION_ERROR(-20005,'PAS DE PLACE');
WHEN ma_exp3 THEN
RAISE_APPLICATION_ERROR(-20006,'IDLOG nexiste pas');
end;
Take a look at the error message, in particular, the parts
Compilation failed, line 10
and
Encountered the symbol ";"
This is line 10:
if (exists(SELECT * FROM PROMOS WHERE :NEW."IDPROMO"=IDPROMO;) )THEN
See the problem?
Your compilation error is being caused by the semicolon in that line. Removing it will help, but your code will still fail to compile, because you can't call EXISTS in PL/SQL outside of SQL. To fix that, see the answers to this question.

PL/SQL and date intervals

I have a date and I'd like to print the offset from that date. I can do this:
dbms_output.put_line(to_char(g_startDate - interval '4' month ,'YYYY-MM-DD'));
and it works fine. The problem is that the interval is variable. When I try this:
dbms_output.put_line(to_char(g_startDate - interval g_dateOffsetAmt month ,'YYYY-MM-DD'));
I get a compiler error.
I thought it might be because g_dateOffsetAmt is an integer so I tried this:
dbms_output.put_line(to_char(g_startDate - interval to_char(g_dateOffsetAmt) month ,'YYYY-MM-DD'));
Though I still get compiler errors saying:
Error: PLS-00103: Encountered the symbol "TO_CHAR" when expecting one of the following:
. ) , * # & | = - + at in is mod remainder not rem =>
.. or != or ~= >= and or like
LIKE2_ LIKE4_ LIKEC_ as between from using || member
SUBMULTISET_
The symbol "," was substituted for "TO_CHAR" to continue.
Line: 704
Error: PLS-00103: Encountered the symbol "MONTH" when expecting one of the following:
. ( ) , * % & | = - + at in is mod remainder not range
rem => .. or != or ~= >= and or
like LIKE2_ LIKE4_ LIKEC_ between || multiset member
SUBMULTISET_
The symbol "." was substituted for "MONTH" to continue.
Line: 704
Is there some other way to do this?
You would probably want to use the NumToYMInterval function
declare
v_interval pls_integer := 4;
begin
dbms_output.put_line( sysdate - NumToYMInterval( v_interval, 'month' ) );
end;
/
There are a couple ways to do this.. Either type your variable being passed in as an interval, or use the function add_months instead:
declare
v_interval INTERVAL YEAR TO MONTH := interval '4' month;
begin
dbms_output.put_line(to_char((sysdate - v_interval), 'MM/DD/YYYY'));
end;
declare
v_interval PLS_INTEGER := 4;
begin
dbms_output.put_line(to_char(add_months(sysdate, -v_interval), 'MM/DD/YYYY'));
end;

Resources