Oracle Database PLSQL Error: PLS-00103 - oracle

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

Related

writing function but been getting this error

the question:
Write a blocK PL/SQL that display the total commission amount of a job id. Use function “compute_commission” that accepts a job id equal to 9 and return his total commission of all corresponding employees.
the error:
`Error at line 11: PLS-00103: Encountered the symbol "DECLARE"
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id in number)
RETURN number
is `
the code:
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id in number)
RETURN number
is
sum_commission number;
begin
select sum(job_id)
into sum_commission from employees
where employee_ref_id = C_employee_id;
return sum_commission;
end compute_commission;
declare
cal_sum_commission number;
begin
cal_sum_commission = compute_commission(cal_sum_commission);
dbms_output.put_line ('employee commission is: ' || compute_commission(cal_sum_commission);
end;
Should be something like this:
CREATE OR REPLACE FUNCTION compute_commission (C_employee_id IN NUMBER)
RETURN NUMBER
IS
sum_commission NUMBER;
BEGIN
SELECT SUM (job_id)
INTO sum_commission
FROM employees
WHERE employee_ref_id = C_employee_id;
RETURN sum_commission;
END compute_commission;
/
DECLARE
cal_sum_commission NUMBER := 12345;
BEGIN
cal_sum_commission := compute_commission (cal_sum_commission);
DBMS_OUTPUT.put_line (
'employee commission is: ' || cal_sum_commission);
END;
/
Note that I modified anonymous PL/SQL block and
added local variable's value (otherwise you'd pass NULL to the function) (you'll, of course, use some valid value; this - 12345 - is just an example)
used local variable in DBMS_OUTPUT.PUT_LINE
terminated statement with a semi-colon (you've had a colon)
fixed assignment operator (:= instead of just =)
Also, is sum_commision really sum of JOB_ID values? Looks strange to me ...

Comparing number with varchar2

I have this function and I need to compare number with varchar.
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
begin
declare odd integer;
declare i_perecentage=0;
begin
if i_odd ='SP'
then
return (0);
end if;
odd:=round(to_number((1-i_perecentage/100)*i_odd),2);
if odd<1
then
return(i_odd);
else
return(round(odd,2));
end if;
end;
end;
/
PS: I edited function and i resolve problem with comparing , now i have another situation that i dont like..
This function returns calculated percentage of i_odd. The problem is that if i pass 0 in i_percentage in results i get result with no decimal places(for example: i_odd = 3.10 and i_percentage = 0 i get odd = 3 but if I pass i_odd = 3.10 and i_percentage = 1 i get odd = 3.10 ).
Why is on i_percentage = 0 i dont get decimal places ??
If you want to validate a varchar2 field as a number in PL/SQL, typically you'd just try converting it to a number and catch the exception.
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
odd number;
BEGIN
-- if i_odd = 'SP' (or another non-number), this will throw an ORA-01722
-- exception which will be caught in the exception block, below
odd := to_number(i_odd); -- you might want a format mask here
--... now you can use "odd" as a number
EXCEPTION WHEN INVALID_NUMBER THEN
return 0;
END;
/
You can also nest a begin..end block in the middle of your code just to catch exceptions, if that works better for you:
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
odd number;
begin
begin
odd := to_number(i_odd); -- you might want a format mask here
exception when INVALID_NUMBER then
odd := 0;
end;
--... now you can use "odd" as a number
end;
/
The reason why you can't catch the invalid_number exception is because you are declaring the input parameter as a number. When you call your function, Oracle tries to convert the string to a number first (and it fails of course, before entering your code at all).
If you change the input parameter to varchar2, then the conversions to number (implicit in this case) is done inside the function, and invalid numbers can be caught and handled as you want (here I'm just returning a different string to denote the issue):
create or replace function is_odd_even(i_num in varchar2)
return varchar2
is
begin
-- conversion to number is done here
if (mod(i_num, 2) = 0) then
return 'EVEN';
else
return 'ODD';
end if;
exception
when INVALID_NUMBER or VALUE_ERROR then
-- do something meaningful
return 'INV';
end;
Usage example:
with x as (
select '1' as val from dual
union all
select 'SP' as val from dual
union all
select '2' as val from dual
)
select x.val, is_odd_even(x.val)
from x;
Output:
1 ODD
SP INV
2 EVEN
SOLUTION:
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return varchar2 as
odd varchar2(10);
ret_value number(4);
begin
if (i_odd ='SP') or i_odd is null then
return 'SP';
else
odd :=ROUND( TO_NUMBER( ( 1 - (play_beting.get_odds_percentage(i_id) / 100 ) ) * TO_NUMBER(i_odd) ), 2);
IF(odd < 1) THEN
ret_value := TO_NUMBER(i_odd);
ELSE
ret_value := to_char(odd,'9999.00');
END IF;
END IF;
RETURN to_char(ret_value,'9999.00');
END getOdds;

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 PLS-00103 while compiling a function

I get this error when I compile my function.
PLS-00103: Encountered the symbol "*" when expecting one of the following:
:= . ( # % ;
Here is the code:
CREATE OR REPLACE FUNCTION IncreaseSalary
(para_empid IN employee.employeeid%TYPE, para_increase IN NUMBER)
RETURN NUMBER
IS
v_SalaryOut NUMBER(10,2);
v_salary2 NUMBER;
BEGIN
SELECT Salary INTO v_Salary2
FROM Employee
WHERE employeeid = para_empid;
--this is the area that pertains to the error
(v_salary2 * para_increase) + v_salary2 = v_salaryout;
RETURN v_SalaryOut;
EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Employee not found.');
END IncreaseSalary;
/
This next part wouldn't be part of the function and is not part of the error
but probably has errors.
DECLARE
v_SalaryOutput NUMBER := IncreaseSalary;
BEGIN
IncreaseSalary('01885', '20%');
DBMS_OUTPUT.PUT_LINE ('Increased Salary: ')
|| TO_CHAR(v_SalaryOutput));
END;
/
The point is to take in two numbers (employeeid and the percentage to increase whatever salary is already listed in the table) and return the updated salary. I don't understand why I can't multiply.
You cannot assign value to variable like that. The target variable should come first. It should be,
v_salaryout := (v_salary2 * para_increase) + v_salary2;
You have declared para_increase as NUMBER. But while calling the function, you are passing '20%' as the value. This will result in numeric or value error: character to number conversion error.
There is an extra bracket in you dbms_output statement.
DBMS_OUTPUT.PUT_LINE ('Increased Salary: ' || TO_CHAR(v_SalaryOutput));

Return N columns from a table function

I need to implement a table function, which I will submit a request with an unknown number of columns. It looks like:
SELECT * from TABLE (function())
where function, for example'SELECT x, y FROM z. I don't know how do this, so I'd like to hear some sort of way to solve, just as an idea.
I think what you are asking is you are getting multiple rows in the o/p when you are using
the function in select statement .
if i create a function as follows:
create or replace function get1job
(id in varchar2)
return varchar2 is
tittle jobs.JOB_TITLE%type;
begin
select job_title into tittle from jobs where job_id=id;
return tittle;
end get1job;
and use it in select statement .
i will write :
select get_job('AD_PRES') from dual;
i will get only one row
if i write :
select get_job('AD_PRES') from jobs;
the number of rows displayed will be equal to the number of rows in the table jobs.
Here is an example for a fully dynamic SQL, you can insert any SELECT statement and it prints out a corresponding HTML:
CREATE OR REPLACE PROCEDURE HtmlTable(sqlStr IN VARCHAR2) IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
columnCount INTEGER;
describeColumns DBMS_SQL.DESC_TAB;
res INTEGER;
c INTEGER;
aCell VARCHAR2(4000);
BEGIN
DBMS_OUTPUT.PUT_LINE('<table>');
DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS(cur, columnCount, describeColumns);
DBMS_OUTPUT.PUT_LINE('<thead><tr>');
FOR i IN 1..columnCount LOOP
DBMS_OUTPUT.PUT_LINE(' <td>'||describeColumns(i).COL_NAME||'</td>');
DBMS_SQL.DEFINE_COLUMN(cur, i, aCell, 4000);
END LOOP;
DBMS_OUTPUT.PUT_LINE('</tr></thead>');
res := DBMS_SQL.EXECUTE(cur);
DBMS_OUTPUT.PUT_LINE('<tbody>');
WHILE (DBMS_SQL.FETCH_ROWS(cur) > 0) LOOP
DBMS_OUTPUT.PUT_LINE('<tr>');
c := 1;
WHILE (c <= columnCount) LOOP
DBMS_SQL.COLUMN_VALUE(cur, c, aCell);
DBMS_OUTPUT.PUT_LINE(' <td>'||aCell||'</td>');
c := c + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('</tr>');
END LOOP;
DBMS_OUTPUT.PUT_LINE('</tbody>');
DBMS_OUTPUT.PUT_LINE('</table>');
DBMS_SQL.CLOSE_CURSOR(cur);
END HtmlTable;
Use this as a base for your application. Then you can execute it like this:
BEGIN
HtmlTable('SELECT x, y FROM z');
END;

Resources