im trying to create 2 package body's in plsql. This is my code:
SET SERVEROUTPUT ON
CREATE OR REPLACE PACKAGE p_locations
AS
FUNCTION f_distance(Lat1 IN NUMBER, Lon1 IN NUMBER, Lat2 IN NUMBER, Lon2 IN NUMBER, Radius IN NUMBER DEFAULT 6387.7) return number;
END p_locations;
/
CREATE OR REPLACE PACKAGE BODY p_locations
AS
FUNCTION f_distance (Lat1 IN NUMBER, Lon1 IN NUMBER, Lat2 IN NUMBER, Lon2 IN NUMBER, Radius IN NUMBER DEFAULT 6387.7)
RETURN NUMBER
IS
-- Convert degrees to radians
DegToRad NUMBER := 57.29577951;
BEGIN
RETURN(NVL(Radius,0) * ACOS((sin(NVL(Lat1,0) / DegToRad) * SIN(NVL(Lat2,0) / DegToRad)) +
(COS(NVL(Lat1,0) / DegToRad) * COS(NVL(Lat2,0) / DegToRad) *
COS(NVL(Lon2,0) / DegToRad - NVL(Lon1,0)/ DegToRad))));
END f_distance;
END p_locations;
/
CREATE OR REPLACE PACKAGE p_winkel
AS
FUNCTION changeOpeningstijd("id" IN number) RETURN boolean;
END p_winkel;
/
CREATE OR REPLACE PACKAGE BODY p_winkel
AS
FUNCTION changeOpeningstijd("id" IN number)
RETURN boolean
IS
dbms_output.put_line('dit is uitgevoerd');
return true;
END changeOpeningstijd;
END p_winkel;
When I run this I gat 3 times a PLS-00103 error. The first is on line 6,16 and says encountered the symbol "." when expecting one of the following: constant exception <an identifier> <a double-quoted delimited-identifier> table long double ref char time timestamp interval date binary national character nchar The symbol "<an identifier>" was substituted for "." to continue.
The strange thing is that when I comment out the 2nd package body everything works fine. Whilst the errors are at the beginning of the first package definition.
Am I doing something stupid wrong here, or can't you create two packages in one session, or what else is going on here, because I don't see any logic in these errors.
You're just missing the BEGIN keyword:
CREATE OR REPLACE PACKAGE BODY p_winkel
AS
FUNCTION changeOpeningstijd("id" IN number)
RETURN boolean
IS
BEGIN ---- this was missing
dbms_output.put_line('dit is uitgevoerd');
return true;
END changeOpeningstijd;
END p_winkel;
/
The line number in the PL/SQL error refers to the PL/SQL block (package, in this case) it is caused by; it isn't the line number in your combined script, as would be the case for a plain SQL error.
When you run this with run script you get three errors reported, not just the one you referred to; and the other two both mention begin:
Errors: check compiler log
6/16 PLS-00103: Encountered the symbol "." when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national character
nchar
The symbol "<an identifier>" was substituted for "." to continue.
8/3 PLS-00103: Encountered the symbol "END" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
The symbol "begin was inserted before "END" to continue.
9/13 PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
begin end function pragma procedure
As Ben mentioned it's a good idea to add a show errors after each spec/body definition to highlight where an error is seen; but you can also query the user_errors view to see the errors related to each invalid object.
Related
im going insane. i dont know whats wrong with this code i see nothing wrong in it. but it kept reading thee same error each time i put the $$ after the "END". please help guys...
here is my code
DELIMITER $$
CREATE FUNCTION fungsi1 (a int)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE nilaiasal INT;
DECLARE teks VARCHAR(50);
SET nilaiasal = a * a;
IF nilaiasal > 100 THEN
SET teks = 'LEBIH DARI SERATUS';
ELSEIF nilaiasal < 100 THEN
SET teks = 'KURANG DARI SERATUS';
INSERT INTO table1 (dataone,datatwo) VALUES(a,teks);
SELECT * FROM table1;
RETURN (nilaiasal);
END $$
DELIMITER ;
And the error is this
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 15
Please help me. I've looked up create functions error and there hasnt been anyone that has a problem near ''.
You might want to consider using a stored procedue instead of a function if you want to return a result set.
You are missing END IF; as Ergest Basha suggested and you are trying to return a result set from a function which is not allowed.
create or replace Type e_record AS Object(
e_uid number,
e_first_name varchar2(50) ,
e_last_name varchar2(50),
e_age number,
e_department varchar2(50),
e_designation varchar2(50),
e_salary number
);
create or replace Type e_record_table IS table Of e_record;
Create or replace package E_package
AS
function list_empDetails return e_record_table pipelined;
end E_package;
/
-------Package Body----------
Create or replace package body E_package
AS
Function list_empDetails return e_record_table pipelined
IS
e_ret e_record_table := e_record_table(null,null,null,null,null,null,null);
Begin
for x in(select e_uid,e_first_name,e_last_name,e_age,e_department,e_designation,e_salary into e_ret from Employee_details) Loop
pipe row(e_ret);
End Loop;
return;
end list_empDetails;
end E_package;
/
And the error i m getting is :
Error at line 8: PL/SQL: ORA-00947: not enough values
Error at line 9: PL/SQL: Statement ignored
Error at line 9: PLS-00382: expression is of wrong type
Error at line 8: PL/SQL: SQL Statement ignored
There are a couple of problems with your code.
Firstly, the not enough values error was because you are querying 7 columns and only providing one variable to put them in in the INTO clause. However, you don't use the INTO clause when looping over the results of a query that way, so the first thing you can do is to get rid of it. Your loop variable x will contain each row of data read from your Employee_details table, you don't need another variable for it.
The next thing to note is that you declared e_ret of type e_record_table. Your pipelined function returns e_record_table, but the type of each row you pipe out needs to be the type your table type contains, not the table type. The expression is of wrong type error is because you were attempting to pipe out a value of type e_record_table. Anyway, you're not selecting anything into e_ret any more, so you can just delete this local variable.
Your loop variable x contains each row read from the query. As written, it contains 7 values, so you could create an e_record row to pipe back using something like the following:
pipe row(e_record(x.e_uid, x.e_first_name, x.e_surname, x.e_age, ...));
However, that makes quite a lot of typing since you are repeating the list of columns in your query. You can avoid the duplicated typing by creating the record in the query and then piping that out:
for x in(select e_record(e_uid,e_first_name,e_last_name,e_age,e_department,e_designation,e_salary) as emp from Employee_details) Loop
pipe row(x.emp);
End Loop;
The full working function is below:
Function list_empDetails return e_record_table pipelined
IS
Begin
for x in(select e_record(e_uid,e_first_name,e_last_name,e_age,e_department,e_designation,e_salary) as emp from Employee_details) Loop
pipe row(x.emp);
End Loop;
return;
end list_empDetails;
I wrote the following program:
create or replace procedure ADDPHONE(IDPELATH in number,IDTHLEFWNO in number )
is
cursor cursor_number is select id_pelath ,TelephoneNumber from PhoneNumbers
where id_pelath>2;
more_than_two_numbers exception;
begin
open cursor_number ;
fetch cursor_number into IDPELATH;
if id_pelath%FOUND then raise more_than_two_numbers
end if;
close cursor_number;
exception
when more_than_two_numbers then
raise_application_error('Error');
END;
/
When I run it, I get the following error:
PLS-00103: Encountered the symbol "END" when expecting one of the following: . ;
The symbol ";" was substituted for "END" to continue.
Could you help me to find the error?
There are multiple issues in the procedure.
Input Parameters are never used in the body.
Cursor is declared to fetch two but FETCH statement is only fetching one.
Incorrect usage of raise_application_error,it requires two input arguments.
I have modified the code that should do the job,
CREATE or REPLACE procedure ADDPHONE(IDPELATH in number,IDTHLEFWNO in number)
is
lv_cnt number(10):=0;
more_than_two_numbers exception;
BEGIN
select COUNT(1) INTO lv_cnt
from PhoneNumbers
where id_pelath = IDPELATH
and TelephoneNumber = IDTHLEFWNO;
if (lv_cnt > 2) then
raise_application_error(-20001,'Error - More than two Numbers ');
end if;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20002,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END ADDPHONE;
/
I am aware that this has been asked so many times, but my problem doesn't seem to go away. I've already put the delimiter in the correct places but i still keep on getting error 'Error(9,1): Encountered the symbol "/" ' at line 9. If I'm not mistaken, the delimiter that causes the error shold be there.
CREATE OR REPLACE PACKAGE FOR_CLASS_NOV2 AS
PROCEDURE PRINT_SNAME(S_NO S.SNO%TYPE);
FUNCTION FIND_MAX_QTY
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY FOR_CLASS_NOV2 AS
PROCEDURE PRINT_SNAME(S_NO S.SNO%TYPE) IS
S_SNAME S.SNAME%TYPE;
BEGIN
SELECT SNAME
INTO S_SNAME
FROM S
WHERE SNO = S_NO;
DBMS_OUT.PUT_LINE('SUPPLIER NAME IS: ' || S_NAME);
END PRINT_SNAME;
FUNCTION FIND_MAX_QTY()
RETURN NUMBER IS
M_QTY NUMBER;
BEGIN
SELECT AX(STY)
INTO M_QTY
FROM SP;
RETURN M_QTY;
END FIND_MAX_QTY;
END;
/
I think you should not use parenthesis in the function when there's no parameters.
Try replacing this:
FUNCTION FIND_MAX_QTY()
RETURN NUMBER IS
With this:
FUNCTION FIND_MAX_QTY
RETURN NUMBER IS
Also, you have a variable named S_SNAME but you're printing S_NAME.
I create a type:
CREATE OR REPLACE TYPE NAGULIVE.DEPOSIT_DATA_TYPE AS OBJECT (
DEPOSIT_NO VARCHAR2 (16 Byte),
ACCT_NAME VARCHAR2 (128 Byte),
DEPOSIT_DT DATE,
EPOSIT_AMT NUMBER (16,2)
);
If I execute the function it will show error. I don't know where I'm wrong.
CREATE OR REPLACE FUNCTION NAGULIVE.GET_DEPOSIT_DETAIL (IN_F_DATE DATE,IN_T_DATE DATE)
RETURN(NAGULIVE.DEPOSIT_DATA_TYPE) AS
BEGIN
RETURN QUERY(SELECT D.DEPOSIT_NO, ACCT_NAME, DEPOSIT_DT, DEPOSIT_AMT
FROM DEPOSIT_ACINFO D
INNER JOIN ACT_MASTER A ON D.CUST_ID=A.CUST_ID
INNER JOIN DEPOSIT_SUB_ACINFO DS ON D.DEPOSIT_NO=DS.DEPOSIT_NO WHERE DS.DEPOSIT_DT>=IN_F_DATE AND DS.DEPOSIT_DT<=IN_F_DATE);
END;
/
The error is
2/7 PLS-00103: Encountered the symbol "(" when expecting one of the following:
<an identifier> <a double-quoted delimited-identifier> self
long double ref char time timestamp interval date binary
national character nchar
4/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following:
<an identifier> <a double-quoted delimited-identifier>
As little as you understand about PL/SQL I doubt you coded the above all by yourself. The error messages refers to the non existing function QUERY.
CREATE OR REPLACE FUNCTION NAGULIVE.GET_DEPOSIT_DETAIL (IN_F_DATE DATE,IN_T_DATE DATE)
RETURN(NAGULIVE.DEPOSIT_DATA_TYPE) AS
BEGIN
RETURN QUERY(SELECT D.DEPOSIT_NO, ACCT_NAME, DEPOSIT_DT, DEPOSIT_AMT
^^^^^
FROM DEPOSIT_ACINFO D
INNER JOIN ACT_MASTER A ON D.CUST_ID=A.CUST_ID
INNER JOIN DEPOSIT_SUB_ACINFO DS ON D.DEPOSIT_NO=DS.DEPOSIT_NO WHERE DS.DEPOSIT_DT>=IN_F_DATE AND DS.DEPOSIT_DT<=IN_F_DATE);
END;
/
The opening bracket indicates that you want to pass parameters to the function but there is no variable called SELECT etc. etc. This of course looks like a SELECT statement. You mention Postgres in your comments. I know nothing about postgres but if that is something you can do in postgres I can attest you that there is no such thing in Oracle PL/SQL.
I guess all this does not bring you further but I must agree with a_horse_with_no_name you must start at square one and start learning PL/SQL.
create or replace function nagulive.get_deposit_detail(
in_f_date date,
in_t_date date
) return deposit_data_type
as
v_deposit_data deposit_data_type;
begin
select deposit_data_type(d.deposit_no, acct_name, deposit_dt, deposit_amt)
into v_deposit_data
from deposit_acinfo d
inner join act_master a on d.cust_id=a.cust_id
inner join deposit_sub_acinfo ds on d.deposit_no=ds.deposit_no
where ds.deposit_dt>=in_f_date
and ds.deposit_dt<=in_f_date;
return v_deposit_data;
end;
/
Although SQL and PL/SQL work well together they are not completely seamless. Unlike PostgreSQL, A SQL statement cannot be used as a native PL/SQL expression. Instead, a variable must be declared, the statement must SELECT INTO that variable, and then the variable is returned.
Also there was a minor syntax problem with the return declaration - there should not be parentheses around the return type. This is different than the return statement, which does optionally allow parentheses.
Those both look like understandable mistakes to me, I'm not sure why this question is getting so much hate.