PLS 00103 error: Encountered the Symbol: IS, end-of -file - sql

The below query when executed is giving errors: PLS 00103. Can you please help me find out the erros here. I have tried other combinations like ELSIF, but all give errors.
CREATE OR REPLACE
FUNCTION fnExpirationDateCondition
(
ExpirDateStr IN VARCHAR2,
OptionDateStr IN VARCHAR2 ) // Error 1 here
RETURN INTEGER ExpirDate DATE; // Error 2 here
OptionDate TIMESTAMP;
IS
BEGIN
ExpirDate :=TO_DATE(ExpirDateStr,'YYYY-MM-DD');
OptionDate :=TO_TIMESTAMP(OptionDateStr, 'YYYY-MM-DD HH24:MI:SS.FF');
IF(ExpirDate > OptionDate) THEN
RETURN 1;
ELSE
IF(ExpirDate < OptionDate) THEN // Error 3 here
RETURN -1;
ELSE
RETURN 0;
END IF;
END IF;
END;
Errors:
1.) Encountered the symbol "ExpirDate" when expecting one of the following:
2.) Encountered the Symbol "IS" when expecting one of the following:
3.) Encountered the symbol "end-of-file" when expecting one of the following:
I have also tried replacing ExpirDate :=TO_DATE(ExpirDateStr,'YYYY-MM-DD') with TO_DATE(ExpirDateStr,'YYYY-MM-DD') INTO ExpirDate. it doesn't seemed to work.
Any suggestions will be really helpful.

The issue is that you've got your variable declarations happening before the IS that marks the start of the function's declaration section.
Try this, instead:
create or replace function fnexpirationdatecondition
(expirdatestr in varchar2,
optiondatestr in varchar2)
return integer
is
expirdate date;
optiondate timestamp;
begin
expirdate := to_date(expirdatestr,'YYYY-MM-DD');
optiondate := to_timestamp(optiondatestr, 'YYYY-MM-DD HH24:MI:SS.FF');
if(expirdate > optiondate) then
return 1;
elsif(expirdate < optiondate) then
return -1;
else
return 0;
end if;
end fnexpirationdatecondition;
/
Or, alternatively, you could just have a single return statement (recommended), and just use a case statement to handle the if-elsif-else logic:
create or replace function fnexpirationdatecondition
(expirdatestr in varchar2,
optiondatestr in varchar2)
return integer
is
expirdate date;
optiondate timestamp;
begin
expirdate := to_date(expirdatestr,'YYYY-MM-DD');
optiondate := to_timestamp(optiondatestr, 'YYYY-MM-DD HH24:MI:SS.FF');
return case when (expirdate > optiondate) then 1
when (expirdate < optiondate) then -1
else 0
end;
end fnexpirationdatecondition;
/

Related

ORACLE SQL function to return JSON response

I have table like below. I am trying to pull all BRKPK_CNTNR_ID, SSP_Q with respect to each OVRPK_CNTNR_ID
enter image description here
Below query runs fine and produces desired result.
DECLARE
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST() ;
counter NUMBER := 1;
BEGIN
FOR ovrpk_detail IN (SELECT OVRPK_CNTNR_ID ,BRKPK_CNTNR_ID,ITEM_DISTB_Q FROM OVRPK_DET od WHERE od.OVRPK_CNTNR_ID='92000000356873110552') LOOP
begin
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('item_distributed_quantity',ovrpk_detail.ITEM_DISTB_Q)
));
counter := counter+1;
END;
END LOOP;
dbms_output.put_line( JSON_UTIL.JSON_ARRAY(json_objects));
END;
I am expecting is to create function that takes OVRPK_CNTNR_ID as input and returns JSON_OBJECT_LIST as output.
Here is my query I tried.
CREATE OR REPLACE FUNCTION get_json_objects(ovrk_cntnr_id IN CHAR)
RETURN JSON_OBJECT_LIST IS
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST();
BEGIN
DECLARE counter NUMBER := 1;
FOR ovrpk_detail IN (SELECT OVRPK_CNTNR_ID ,BRKPK_CNTNR_ID FROM OVRPK_DET od WHERE od.OVRPK_CNTNR_ID= ovrk_cntnr_id) LOOP
begin
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID)
));
counter := counter+1;
END;
END LOOP;
RETURN json_objects;
END;
DECLARE
json_return_object JSON_OBJECT_LIST;
ovrk_cnt_i char := '92000000356873110552'
BEGIN
json_return_object := get_json_objects(ovrk_cnt_i);
dbms_output.put_line('JSON Object is: ' || json_return_object);
END;
I am missing something, would anyone help me to resolve this issue? Thank you
Note: I am using Oracle 12.c database which does not support JSON however, JSON_UTIL is library written internally to address same
We do not have your packages or functions so this is difficult to test.
Your code has a DECLARE without a corresponding BEGIN or END. If you get rid of all the unnecessary DECLARE/BEGIN/END statements then you can simplify it to:
CREATE OR REPLACE FUNCTION get_json_objects(
ovrk_cntnr_id IN CHAR
)
RETURN JSON_OBJECT_LIST
IS
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST();
counter NUMBER := 1;
BEGIN
FOR ovrpk_detail IN (
SELECT OVRPK_CNTNR_ID,
BRKPK_CNTNR_ID
FROM OVRPK_DET
WHERE OVRPK_CNTNR_ID = ovrk_cntnr_id
) LOOP
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID)
)
);
counter := counter+1;
END LOOP;
RETURN json_objects;
END;
/
If your package functions are callable from SQL then you should be able to simplify it further to:
CREATE OR REPLACE FUNCTION get_json_objects(
i_ovrpk_cntnr_id IN OVRPK_DET.OVRPK_CNTNR_ID%TYPE
) RETURN JSON_OBJECT_LIST
IS
json_objects JSON_OBJECT_LIST;
BEGIN
SELECT JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id', OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id', BRKPK_CNTNR_ID)
)
)
BULK COLLECT INTO json_objects
FROM OVRPK_DET
WHERE OVRPK_CNTNR_ID = i_ovrpk_cntnr_id;
RETURN json_objects;
END;
/
DECLARE
json_return_object JSON_OBJECT_LIST;
ovrk_cnt_i OVRPK_DET.OVRPK_CNTNR_ID%TYPE := '92000000356873110552'
BEGIN
json_return_object := get_json_objects(ovrk_cnt_i);
dbms_output.put_line('JSON Object is: ' || json_return_object);
END;
/

A functions code is written in oracle. I am unable to understand what it is doing

Here is the function:
create or replace FUNCTION FUNC_PART(
p_TEXT varchar2,
p_COLUMN number,
p_SEPARATOR varchar2
) RETURN varchar2 AS
v_POS_ number;
v_POS2 number;
V_COLUMN NUMBER;
BEGIN
V_COLUMN:=p_COLUMN;
v_POS_ := 1;
v_POS2 := INSTR(p_TEXT, p_SEPARATOR, v_POS_);
WHILE (V_COLUMN >1 AND v_POS2> 0) LOOP
v_POS_ := v_POS2 + 1;
v_POS2 := INSTR(p_TEXT, p_SEPARATOR, v_POS_);
V_COLUMN :=V_COLUMN - 1;
END LOOP;
IF V_COLUMN > 1 THEN
v_POS_ := LENGTH(RTRIM(p_TEXT)) + 1;
END IF;
IF v_POS2 = 0 THEN
v_POS2 := LENGTH(RTRIM(p_TEXT)) + 1;
END IF;
RETURN SUBSTR (p_TEXT, v_POS_, v_POS2 - v_POS_);
END;
I did not understand this code carefully, but from the results, the following two pieces of code have the same meaning.
select FUNC_PART('asdfghsdfg', 3, 's')
from dual;
select regexp_substr('asdfghsdfg', '[^s]+', 1, 3)
from dual;
This is likely to be migrated from other databases to the code in oracle, because oracle does not need such a custom function

Error ORA-06530 from function that returns an object type

I have the following function GET_UN_COLLECTED_4LD which returns the type ld_data_type:
CREATE OR REPLACE TYPE ld_data_type AS OBJECT(collected NUMBER, uncollected NUMBER);
/
CREATE OR REPLACE FUNCTION GET_UN_COLLECTED_4LD (VAPPOINTOFCAID NUMBER,
VPREVLIQUIDATE NUMBER,
VCURRLIQUIDATE NUMBER,
VNEXTLIQUIDATE NUMBER,
YEPT NUMBER)
RETURN LD_DATA_TYPE
AS
OUT_VAR LD_DATA_TYPE;
VNETV23 NUMBER;
VNETV24 NUMBER;
VCURR23 NUMBER;
VCURR24 NUMBER;
VCOLLECTED NUMBER;
VUNCOLLECTED NUMBER;
BEGIN
SELECT SUM (NETX) - SUM (NETP)
INTO VNETV23
FROM VIEW_CUSTOMER_TRN4INVS4LD
WHERE APPOINTOFCAID = VAPPOINTOFCAID AND VAT = ABS (1.23);
SELECT SUM (NETX) - SUM (NETP)
INTO VNETV24
FROM VIEW_CUSTOMER_TRN4INVS4LD
WHERE APPOINTOFCAID = VAPPOINTOFCAID AND VAT = ABS (1.24);
VCOLLECTED := 0;
VUNCOLLECTED := 0;
CASE
WHEN YEPT = 0
THEN
VCURR24 := VCURRLIQUIDATE - VNETV24;
CASE
WHEN VCURR24 > 0
THEN
VCOLLECTED := VNETV24 * 1.24;
VCURR23 := VCURRLIQUIDATE - VNETV23;
CASE
WHEN VCURR23 > 0
THEN
VCOLLECTED := -999;
ELSE
VCOLLECTED :=
VCOLLECTED + ( (VCURRLIQUIDATE - VCURR24) * 1.23);
END CASE;
ELSE
VCOLLECTED := -1999;
END CASE;
ELSE
OUT_VAR.COLLECTED := -888;
OUT_VAR.UNCOLLECTED := -889;
END CASE;
SELECT VCOLLECTED, VUNCOLLECTED
INTO OUT_VAR.COLLECTED, OUT_VAR.UNCOLLECTED
FROM DUAL;
/*
OPEN buffer_cur;
FETCH buffer_cur INTO out_var.val1, out_var.val2;
CLOSE buffer_cur; */
RETURN OUT_VAR;
END GET_UN_COLLECTED_4LD;
When I call the function like
select GET_UN_COLLECTED_4LD(171231, 42240, 31680, 0, 0) from dual;`
I get an error:
Execution (50: 8): ORA-06530: Reference to uninitialized composite
ORA-06512: at "C##SOLSA.GET_UN_COLLECTED_4LD", line 56
I'm use Oracle 12c Standard edition.
How should I be calling the function GET_UN_COLLECTED_4LD and Where is the problem that causes the error?
As the error says, you haven't initialised your object variable:
...
RETURN LD_DATA_TYPE
AS
OUT_VAR LD_DATA_TYPE := new LD_DATA_TYPE(null, null);
...
Your logic is slightly confused though; at the end of your case you do:
ELSE
OUT_VAR.COLLECTED := -888;
OUT_VAR.UNCOLLECTED := -889;
but then overwrite the value immediately afterwards with:
SELECT VCOLLECTED, VUNCOLLECTED
INTO OUT_VAR.COLLECTED, OUT_VAR.UNCOLLECTED
FROM DUAL;
Possibly you meant to set VCOLLECTED and VUNCOLLECTED in that ELSE. If you did that then you wouldn't need to initialise OUT_VAR, as the first remaining reference would create it; which you could do as:
OUT_VAR := LD_DATA_TYPE (VCOLLECTED, VUNCOLLECTED);
instead of selecting from dual; or you could not have the local variable at all and just do:
...
ELSE
VCOLLECTED := -888;
VUNCOLLECTED := -889;
END CASE;
RETURN LD_DATA_TYPE (VCOLLECTED, VUNCOLLECTED);
END GET_UN_COLLECTED_4LD;
First you need to initialize your object type OUT_VAR before you can set its properties like this:
OUT_VAR:= LD_DATA_TYPE(0,0);
See the details here.

These bits of code all have errors in how can i fix this? [duplicate]

This question already has answers here:
I keep getting an error next to the return VARCHAR(4)
(2 answers)
Closed 8 years ago.
This has an error next to VARCHAR2 and (4):
CREATE OR REPLACE FUNCTION Employee_exists
(p_employee_id IN NUMBER)
RETURN VARCHAR2(4);
AS
BEGIN
SELECT employee_id
FROM employees
WHERE employee_id = p_employee_id;
RETURN 'true';
END Employee_exists;
Here it says there is an error next to the decleration of v_years_service:
CREATE OR REPLACE FUNCTION Calculate_Bonus(p_salary IN NUMBER, p_startdate IN DATE)
RETURN NUMBER -- here it errors
AS
v_years_service NUMBER;
BEGIN
v_years_service := TRUNC(Months_Between(SYSDATE, v_startdate) /12);
IF (v_years_service <2) THEN
p_bonus := v_salary * 0.02;
ELSE
IF (v_year_service <2) THEN
p_bonus := v_salary * 0.04;
ELSE
p_bonus := v_salary * 0.05;
RETURN p_bonus;
END IF;
END Calculate_Bonus;
/
show err
For the Employee_exists function, change this:
RETURN VARCHAR2(4)
To this:
RETURN VARCHAR
For the Calculate_bonus function, move this line...
v_years_service NUMBER;
... so it's under the AS line:
CREATE OR REPLACE FUNCTION Calculate_bonus(p_salary IN NUMBER, p_startdate IN DATE)
RETURN NUMBER
AS
v_years_service NUMBER; --here is where the error appears
BEGIN
... and the rest
Finally, there's this line:
v_years_service = TRUNC(MONTHS_BETWEEN(SYSDATE, v_startdate) /12);
The variable assignment is always :=, so change it to this:
v_years_service := TRUNC(MONTHS_BETWEEN(SYSDATE, v_startdate) /12);
Addendum A Also note the comment from #JoeW under your question. Joe states - correctly - that your ELSE condition will never be hit.
Addendum B
Here's the full function. You may also want to round the return value, as a salary multiplied by 0.02 or 0.05 can give fractional cents. To round, substitute RETURN ROUND(p_bonus, 2); for RETURN p_bonus;.
CREATE OR REPLACE FUNCTION Calculate_Bonus(p_salary IN NUMBER, p_startdate IN DATE)
RETURN NUMBER
AS
v_years_service NUMBER;
v_bonus NUMBER;
BEGIN
v_years_service := TRUNC(Months_Between(SYSDATE, p_startdate) /12);
IF (v_years_service <2) THEN
v_bonus := p_salary * 0.02;
ELSE
v_bonus := p_salary * 0.05;
END IF;
RETURN v_bonus;
END Calculate_Bonus;
/

Check if a file exists?

trying to check whether the file I want to read exists or not.
Here are another approaches:
Using BFILE and fileexists function of dbms_lob package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_file_loc bfile;
begin
l_file_loc := bfilename(upper(p_DirName), p_FileName);
return dbms_lob.fileexists(l_file_loc); -- 1 exists; 0 - not exists
end;
Using fgetattr function of utl_file package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_fexists boolean;
l_flen number;
l_bsize number;
l_res number(1);
begin
l_res := 0;
utl_file.fgetattr(upper(p_DirName), p_FileName, l_fexists, l_flen, l_bsize);
if l_fexists
then
l_res := 1;
end if;
return l_res;
end;
Use UTL_FILE.FGETATTR function.
This function is designed specifically for this purpose.
Syntax:
UTL_FILE.FGETATTR(
location IN VARCHAR2,
filename IN VARCHAR2,
fexists OUT BOOLEAN,
file_length OUT NUMBER,
block_size OUT BINARY_INTEGER);
Example:
DECLARE
fexists BOOLEAN;
file_length NUMBER;
block_size BINARY_INTEGER;
BEGIN
UTL_FILE.FGETATTR('MY_ORA_DIRECTORY', 'my_file_name.csv', fexists, file_length, block_size);
IF fexists THEN
-- Do something
-- ...
END IF;
END IF;
Oracle documentation:
https://docs.oracle.com/database/121/ARPLS/u_file.htm#ARPLS70915
One more useful link:
https://www.foxinfotech.in/2018/09/how-to-check-if-file-exists-in-pl-sql.html
Creating a function that checks if a file exists is fairly easy by just trying to open it and catching any exceptions (this example function taken from AskTom)
CREATE OR REPLACE FUNCTION file_exists(p_fname IN VARCHAR2) RETURN BOOLEAN
AS
l_file UTL_FILE.FILE_TYPE;
BEGIN
l_file := UTL_FILE.FOPEN(SUBSTR( p_fname, 1, instr(p_fname,'/',-1) ),
SUBSTR( p_fname, instr( p_fname, '/', -1)+1 ), 'r' );
UTL_FILE.FCLOSE( l_file );
RETURN TRUE;
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN RETURN FALSE;
WHEN UTL_FILE.INVALID_OPERATION THEN RETURN FALSE;
END;
/
Then you can just use;
IF ( file_exists( 'MED_LIST_19_OCT_12.csv' ) )
...