How to look for words in a CLOB - sql

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.

Related

Missing Keyword when trying to Select into

So I have a function to return an Average of a column such as
CREATE OR REPLACE FUNCTION avgCol
RETURN DEC IS avgNum DEC;
BEGIN
SELECT AVG(myCol)
INTO avgNum
FROM MyTable;
RETURN avgNum;
END;
/
While trying to test the results, i have the following
SELECT avgCol
INTO RESULT
FROM DUAL;
but it gives me the error
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action:
Error at Line: 175 Column: 6
Where line 175 is INTO RESULT. As far as I know, this is a scalar function and I'm trying to return a signal variable so it should work right? What keyword am I missing here?
Also I know I can just use AVG(), but I am learning how to create a scalar function. this is strictly for learning purposes.
While testing your code (which should be ok), you need
SELECT avgCol AS result FROM DUAL;
'INTO' assigns the result value to a PL/SQL variable; 'AS' creates an alias/name for a SQL SELECT (not PL/SQL) result column/field.

Unable to remove carriage returns in a LONG data type column using REPLACE function

I am working on a LONG column in Oracle SQL Developer and this column contains carriage returns that need to be removed. The error I'm getting after using :
REPLACE ( col_name , CHR(13) , '' ) is :
ORA-00932: inconsistent datatypes: expected CHAR got LONG
00932. 00000 - "inconsistent datatypes: expected %s got %s"
Is there a workaround for this ?
Answers or suggestions will be much appreciated!
You will not be able to do almost anything with LONG data type columns. You should convert them to CLOB. You just found a reason why that is.
https://docs.oracle.com/cd/B28359_01/appdev.111/b28393/adlob_long_lob.htm
There is a to_lob() function to convert LONG to CLOB, but that can only be used in the select portion of an insert statement (that is, it can only be used to convert a LONG column to a CLOB column). After the conversion, you should have no problems using text functions on the resulting CLOB. You may also want to look at CLOB-specific functions in the DBMS_LOB package:
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_lob.htm#ARPLS600

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. :-)

Package Errors. What Am I doing wrong?

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

PLSQL archiving LONG datatype, error:

Im using Oracle 11g, attempting to move anything older than 90days to the History table using PL/SQL..BUT i have one of the columns using datatype of LONG. So i have found the SQL that i thought should work but it gives errors:
BEGIN
FOR ROW IN
(SELECT MESSSAGE_KEY,
DISTRIBUTION_ID,
MESSAGE,
SYSTEM_NAME,
MESSAGE_TYPE,
MESSAGE_NAME,
MESSAGE_STATUS,
LATEST_INBOUND,
CREATETS,
MODIFYTS,
CREATEUSERID,
MODIFYUSERID,
CREATEPROGID,
MODIFYPROGID,
LOCKID,
ENTITY_KEY,
ENTITY_NAME,
ENTITY_VALUE
FROM NWCG_INBOUND_MESSAGE
WHERE TO_CHAR (createts, 'YYYYMMDD') >= TO_CHAR ((sysdate-90), 'YYYYMMDD')
)
LOOP
INSERT INTO NWCG_INBOUND_MESSAGE_H
VALUES (
ROW.MESSSAGE_KEY,
ROW.DISTRIBUTION_ID,
ROW.MESSAGE,
ROW.SYSTEM_NAME,
ROW.MESSAGE_TYPE,
ROW.MESSAGE_NAME,
ROW.MESSAGE_STATUS,
ROW.LATEST_INBOUND,
ROW.CREATETS,
ROW.MODIFYTS,
ROW.CREATEUSERID,
ROW.MODIFYUSERID,
ROW.CREATEPROGID,
ROW.MODIFYPROGID,
ROW.LOCKID,
ROW.ENTITY_KEY,
ROW.ENTITY_NAME,
ROW.ENTITY_VALUE
);
END LOOP;
END;
This is the error i am getting:
Error report:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 2
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause:
*Action:
From my research it looks like this error has been about a lot, but i cant find any of peoples solutions to work.... any ideas?
The long datatype has been one of the reasons why I've always advised against storing documents or long string in an Oracle database. Without reverting to C and OCI, it is hard to use.
Now we have clob and blob which are reasonable usable in PL/SQL and SQL. But there are still many occurrences of the LONG datatype to be found of it, also in the Oracle data dictionary. Especially in XXX_VIEWS (user_views, all_views, dba_views) it is a real problem. Maybe the original developer should have named it UNUSABLE :-).
There is a workaround when the LONG contents are smaller than 32 KB; for full functionality I would recommend migrating to CLOB or using C. Good luck!
--
-- This sample code works when the long is smaller than 32 KB.
-- It is known to work on 9i, 10g, 11g r1, 11g r2, but it assumes
-- that a LONG smaller than 32 KB can be put in a PL/SQL variable.
-- And then cast.
--
-- You might want to add an exception handler to handle exceptions
-- when the size is larger than 32 KB. In this sample, this situation
-- can not occur; the where clause with text_length ensures that.
--
declare
l_text_as_long long;
l_text_as_clob clob;
l_text_length user_views.text_length%type;
begin
select viw.text
, viw.text_length
into l_text_as_long
, l_text_length
from user_views viw
where viw.view_name = upper(l_object_name)
and viw.text_length <= 32767 /* To fix a problem when accessing a view that is larger than 32K, we have this condition. */
;
l_text_as_clob := cast(l_text_as_long as clob);
... do something interesting ...
end;