Package Errors. What Am I doing wrong? - sql

I'm trying to create a package that works out the number of days between two dates, I'm aware I have probably got this miles wrong, I am really struggling to troubleshoot this. My knownledge is low on oracle, I'm still quite new to this. The package I've written is below, but I am getting the error shown at the bottom.
How do I resolve this?
CREATE OR REPLACE PACKAGE PACKNAME
AS
FUNCTION TIME_SCALE RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY PACKNAME
AS closed_date := '28-APR-14'
FUNCTION TIME_SCALE RETURN NUMBER;
IS BEGIN
TRUNC(mrc.closed_date - mrc.open_date) AS days_difference FROM TASKS mrc;
END;
​
Error at line 2: 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
I have substituted some of the names to make them clearer for you to read.
The function is to output the number of days it has taken for a task to be completed. The columns basically include the date_opened and date_closed in simple terms as well as a few others and a unique ID which I believe is a sequence.

Try this:
CREATE OR REPLACE PACKAGE PACKNAME
AS
FUNCTION TIME_SCALE
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY PACKNAME
AS
closed_date VARCHAR2(50):= '28-APR-14';
days_difference NUMBER;
FUNCTION TIME_SCALE
RETURN NUMBER
IS
BEGIN
SELECT TRUNC(mrc.closed_date - mrc.open_date) INTO days_difference
FROM TASKS mrc;
RETURN days_difference;
END;
END;
What was wrong:
1) You have missed the type for closed_date
2) You had an ';' after RETURN NUMBER in function declaration
3) You have missed SELECT clause inside function
4) You have missed END for the package

Related

How to look for words in a CLOB

I have been at this process for a wile and have used INSTR() and have never had any problem with it until
now. a.review is a CLOB and INSTR() has worked in a simple SELECT statement.
DECLARE
lv_hotel NUMBER;
seed_cnt NUMBER;
lv_cat NUMBER;
lv_pol NUMBER;
f NUMBER;
BEGIN
FOR f IN 1..4176
LOOP
SELECT a.IDHotel ,DBMS_LOB.INSTR(a.review, b.seed_words), b.CATEGORYID, SUM(b.Polarity)
INTO lv_hotel, seed_cnt, lv_cat, lv_pol
FROM review a, SEEDWORDS b
GROUP BY a.IDHOTEL, b.CategoryID, DBMS_LOB.INSTR(a.review, b.seed_words), a.review, b.seed_words;
FOR lv_cat IN 1..4
LOOP
INSERT INTO RATINGS (RATING)
VALUES(lv_pol);
END LOOP;
END LOOP;
END;
When I run the above code I get the errors as seen below:
Error report -
ORA-00932: inconsistent datatypes: expected - got CLOB
ORA-06512: at line 11
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Is there away around this? Should I use a REGEX function?
DBMS_LOB.INSTR
INSTR Functions
This function returns the matching position of the nth
occurrence of the pattern in the LOB, starting from the offset you
specify.
Update:
I never realized you're doing group by a.review. You cannot use CLOB column in a group by clause. No way around that unless you cast it to varchar2. That logic will need to be reconsidered.

User defined function with XMLSERIALIZE

I am writing a user defined function in pl/sql for an Oracle database. The function purpose is converting an xml field to a clob. This is the code:
CREATE OR REPLACE FUNCTION IDS_ORA.castField_xml_to_clob (xmlField IN XMLTYPE)
RETURN CLOB
AS
BEGIN
RETURN XMLSERIALIZE(CONTENT xmlField AS CLOB NO INDENT)
END;
/
Compiling fails with this error:
PLS-00103: Encountered the symbol "XMLFIELD" when expecting one of the
following: . ( ) , * # % & = - + < / > at in is mod remainder not
rem => <> o != o ~= >= <= <> and or like like2
like4 likec as between from using || multiset member submultiset
Function:IDS_ORA.CASTFIELD_XML_TO_NVARCHAR(IDS_ORA#172.25.1.134:1522:sviluppo)
5 31
It seems a generic error to me, so I tried using XMLSERIALIZE directly inside a query and it works.
SELECT XMLSERIALIZE(CONTENT "AttributesValue" AS CLOB no INDENT)
FROM IDS_ORA."Job";
This means the syntax is correct, what is it complaining about?
XMLSerialize isn't a native PL/SQL function. Many SQL functions can be called directly in PL/SQL, such as to_date(); unfortunately this isn't one of them. (I don't think any of the XML-related functions can be, in fact).
In PL/SQL expressions, you can use all SQL functions except:
...
XML functions (such as APPENDCHILDXML and EXISTSNODE)
You can't use direct assignment, so you need to use a query:
CREATE OR REPLACE FUNCTION castField_xml_to_clob (xmlField IN XMLTYPE)
RETURN CLOB
AS
result CLOB;
BEGIN
SELECT XMLSERIALIZE(CONTENT xmlField AS CLOB NO INDENT)
INTO result
FROM dual;
RETURN result;
END;
/
Function CASTFIELD_XML_TO_CLOB compiled
Which adds another context switch, so unless you're trying to have a common place to control indent options for all formatted XML so you can change them all in one place, I'm not sure this gains you anything over just calling XMLSerialize directly wherever you were going to call this UDF.

Why am I receiving PLS-00103 when attempting to create this simple function?

I am trying to create this function:
create or replace function g(sN int) return char(3) as
t char(3);
begin
select pt into t from (
select pTT as pt, pC
from ple
order by pC asc
) where sN <= pC and rownum <= 1;
return t;
end;
/
I receive this following errors:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/31 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
; is authid as cluster order using external varying character
large deterministic parallel_enable pipelined aggregate
result_cache accessible
2/9 PLS-00103: Encountered the symbol "CHAR" when expecting one of
the following:
, from into bulk
The symbol "," was substituted for "CHAR" to continue.
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/16 PLS-00103: Encountered the symbol ";" when expecting one of the
following:
. ( , * % & - + / at mod remainder rem <an identifier>
<a double-quoted delimited-identifier> <an exponent (**)> as
from into || multiset bulk
11/8 PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
end not pragma final instantiable order overriding static
member constructor map
My questions:
In general, why do these errors happen or signify?
More specifically, why am I receiving this error?
My research:
There are a number of questions involving PLS-00103 on SO, but none of them seem to fit my function.
Some problems that I have seen on SO that caused PLS-00103 are:
The accidental use of a reserved word, like max or min, as a variable name.
The incorrect use of looping structure keywords, like using EXIT LOOP to end a
loop instead END LOOP.
Incorrectly assigning a value to a variable, like x + 9 = x.
Of course, this isn't a comprehensive list of the problems I've indicated as PLS-00103, but I don't think my function applies to any of the ones I have seen.
Parameters can only specify the base type, not precision, scale, length etc.
return char(3)
should be
return char
or perhaps better,
return ple.ptt%type
btw char is almost never a good idea. It doesn't avoid some overhead of variable length strings as some people seem to think, and it doesn't ensure that values such as 3-letter ISO currency codes will have the expected number of letters. All it will do is add blank spaces to the end of non-null values, sometimes when you don't expect it to, leading to obscure bugs. It was added solely for ANSI compatibility reasons, and you are really not supposed to use it in developing new systems using Oracle.

Trying to use a where statement in cursor creation (PL/SQL)

I'm trying to create a block that accepts input from a prompt and uses that input to filter the result set for the cursor. Keep in mind I'm a novice here so I maybe making a very routine mistake, and thank you for your help. My current code is below.
Set serveroutput on
DECLARE
ACCEPT a PROMPT “Please Enter a Date, eg. Format - 01 or 30"
datev char
datev := &a;
CURSOR cur_day_cursor IS
SELECT Arrival_Date Adate
FROM FLIGHT
WHERE TO_CHAR(Arrival_Date, ‘DD’) = datev;
cur_day_cursor_var cur_day_cursor%ROWTYPE;
BEGIN
OPEN Cur_day_cursor;
LOOP
Fetch Cur_day_cursor
INTO cur_day_cursor_var;
EXIT WHEN cur_day_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (cur_day_cursor_var.Adate);
END LOOP;
IF cur_day_cursor%ISOPEN THEN
CLOSE cur_day_cursor;
END IF;
END;
The where statement is causing my errors, so I was thinking that I may have to let the cursor collect all the data and then filter it when displaying, but I'm not sure if I can even do that.
The error I keep receiving ERROR at line 9:-
ORA-06550: line 9, column 1:
PLS-00103: Encountered the symbol "WHERE" when expecting one of the following:
begin function pragma procedure subtype type
current cursor delete
exists prior
I don't know exactly why Oracle is reporting the error at the WHERE. Sometimes the parser gets pretty confused by bad syntax and doesn't point to the real problem. You have several syntax errors before the cursor definition.
ACCEPT is a SQLPlus command, not a PL/SQL statement. Move your ACCEPT line above the DECLARE.
Also, your variable declaration and initialization are incorrect. The assignment should be part of the declaration line; you need to provide a length for the CHAR datatype; and the substitution value should be in quotes to be treated as a string. A valid version of your lines would be:
datev char(2) := '&a';
I ran the same query as above, and got the results perfectly fine.
You have few syntax as well as logical error which I corrected in your query. The syntax error(s) are -
datev char
datev := &a;
You can't do such an initialization in PL/SQL. You probably have to complete it in a single line like below -
datev char := &a;
The logical mistake(s) are -
Why use a CHAR variable to store data when you know that the value being returned is NUMBER.
You expect numbers from 1-31; then why do you choose the default size of char which as 1. It will fail if you provide a 2-digit number
Even if you increase the size of CHAR to CHAR(2), you will not get results when the users enters a number like 1 or 01, because for character wise comparison, '1' != '1 '(Mark the extra space at the end, because of char(2)); and also '1' != '01'.
The only solution for above is to use a NUMBER datatype.
Now here I am posting my query which is similar to your query, with a change of column name and table name. Please replace with your required names and try -
(Take care not to execute the ACCEPT....) with the PL/SQL block. It should be done in the SQL prompt first and then the other DECLARE section should be run.
--ACCEPT a NUMBER PROMPT 'Please Enter a Date, eg. Format - 01 or 30 :'
--Run the above line first in SQL Prompt and then execute the rest as whole
DECLARE
datev NUMBER(2) := &a;
CURSOR cur_day_cursor IS
SELECT Ename, HireDate Adate
FROM Emp
WHERE TO_CHAR(HireDate, 'D') = datev;
cur_day_cursor_var cur_day_cursor%ROWTYPE;
BEGIN
OPEN Cur_day_cursor;
LOOP
Fetch Cur_day_cursor
INTO cur_day_cursor_var;
EXIT WHEN cur_day_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (cur_day_cursor_var.Adate);
END LOOP;
IF cur_day_cursor%ISOPEN THEN
CLOSE cur_day_cursor;
END IF;
END;
/
It appears that the problem is that the single-quotes around ‘DD’ aren't single-quotes. It looks like the code was created in an editor which changes apostrophes into those special "look kind of like single quotes but aren't really" characters. Replace the original version of the WHERE clause with the following:
WHERE TO_CHAR(Arrival_Date, 'DD') = datev;
and I suspect you'll be fine.
And get yourself a good code editor. :-)

How can I debug a "division by zero" error in postgresql

I am using many different views and plpgsql functions/aggregates in a single SELECT. When I run this SELECT on certain data sets, I get a division by zero error. Unfortunately, I don't get any details where exactly the division by zero occurs.
Is there I good way to pinpoint the exact place where the problem occurs?
Running the same code in psql will yield more helpful information, like:
ERROR: division by zero
CONTEXT: PL/pgSQL function "mean_estimator_sfunc" line 10 during statement block local variable initialization
Post your function. Here's some good example from Oracle documentation on how to avoid your exception. Same can be done with SQL only:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/errors.htm
DECLARE
stock_price NUMBER := 9.73;
net_earnings NUMBER := 0;
pe_ratio NUMBER;
BEGIN
pe_ratio :=
CASE net_earnings
WHEN 0 THEN NULL
ELSE stock_price / net_earnings
end;
END;
/