Oracle text: catsearch does not support functional invocation - sql

Here's my setup:
CREATE TABLE CUSTOMER
(
CUSTOMER_ID NUMBER(9, 0) NOT NULL
, CUSTOMER_NAME VARCHAR2(61 BYTE)
);
CREATE INDEX CTXCAT_CUSTOMER_NAME
ON CUSTOMER (CUSTOMER_NAME) INDEXTYPE IS CTXSYS.CTXCAT;
My (simplified) query:
select /*+ INDEX(customer CTXCAT_CUSTOMER_NAME)*/*
from customer
where CATSEARCH(customer_name,'ltd Anderson',null) > 0 or customer_id > 100
Error:
Error starting at line 1 in command: select /*+ INDEX(customer
CTXCAT_CUSTOMER_NAME)/ from customer where
CATSEARCH(customer_name,'ltd Anderson',null) > 0 or customer_id > 100
Error report: SQL Error: ORA-20000: Oracle Text error: DRG-10849:
catsearch does not support functional invocation
20000. 00000 - "%s"
*Cause: The stored procedure 'raise_application_error'
was called which causes this error to be generated.
*Action: Correct the problem as described in the error message or contact
the application administrator or DBA for more information.
The HINT suggestion came from here: https://forums.oracle.com/message/2847094 and clearly doesn't work for me.
Any ideas how to resolve?

The problem is that most probably in your query Oracle uses CATSEARCH as a function invocation, rather than using your index. This is because you have the OR condition and Oracle has to check every row in your table. That's also the reason why HINT won't help. Can you show us the execution plan?
Perhaps try this:
select *
from customer
where customer_id > 100
UNION
select /*+ INDEX(customer CTXCAT_CUSTOMER_NAME)*/ *
from customer
where CATSEARCH(customer_name,'ltd Anderson',null) > 0;
(the hint shouldn't be necessary in above example)

Related

Use table in order by case when does not work

I am running this query but I get an error
select *
from dog
order by case
when exists(
select 1 from dogfood where dog.dogid = dogfood.dogid)
then '1'
else '0' end;
So 2 tables, dog and dogfood which both have a dogid column. I get this error:
[42703][-206] "DOG.DOGID" is not valid in the context where
it is used.. SQLCODE=-206, SQLSTATE=42703, DRIVER=4.26.14
[56098][-727] An error occurred during implicit system action type
"2". Information returned for the error includes SQLCODE "-206",
> SQLSTATE "42703" and message tokens "DOG.DOGID"..
> SQLCODE=-727, SQLSTATE=56098, DRIVER=4.26.14
I just want to order the dog by if it has a row in dogfood. A solution would be querying the result in the select clause and refer to it in the order by clause, but I want it in the order by clause for my application. I am curious why this query isn't working, I double checked for syntax errors but I could not find any. Am I missing something obvious? I would expect I could refer to a table in the order by which I queried in the select/from clauses.
See documentation
sort-key-expression
An expression that is not simply a column name or an unsigned integer constant. The query to which ordering is applied must be a
subselect to use this form of sort-key. The sort-key-expression cannot
include a correlated scalar fullselect (SQLSTATE 42703) or a function
with an external action (SQLSTATE 42845).
But since it is not correlated you can use IN with a fullselect
select *
from dog
order by
case when dog.dogid in (select dogid from dogfood)
then '1' else '0' end;

Trigger keeps failing to compile. Claims table not found when table exists

All the tables that are called definitely exist. I double checked the spelling as well.
The errors sqldeveloper gives are not very helpful and I can't seem to figure out why this is failing. I am attempting to make a trigger which updates the top5restaurants table when a new review comes in. I have a procedure which parses the review and adds them to the rating table. The top5restaurant table maintains the restaurants with the 5 highest ratings.
drop view bestratings_rest;
create view bestratings_rest(rid, rate) as
(select distinct rid, max(stars) from rating
group by rid);
drop table top5restaurants;
create table top5restaurants(rid int);
insert into top5restaurants rid
select rid from
(select rid, rate from bestratings_rest r
order by r.rate asc)
where rownum <=5;
drop view top5rest;
create view top5rest as
select rid, best from(
select t.rid, best from top5restaurants t
inner join (select distinct rid, max(stars) as best from rating
group by rid) b
on t.rid = b.rid);
create or replace trigger top5_trigger
after insert on rating
for each row
declare
minrow top5rest%rowtype;
restrid restaurant.rid%type;
restname restaurant.name%type;
begin
insert into minrow
select rid, min(best) from top5rest;
insert into restname
select rid from restaurant
where :new.rid = restaurant.rid;
if :new.stars > minrow.best then
DELETE FROM top5restaurants
where top5restaurants.rid = :new.rid;
insert into top5restaurants values(rid);
end if;
end;
/
--
--
begin
update_reviews('Jade Court','Sarah M.', 4, '08/17/2017');
update_reviews('Shanghai Terrace','Cameron J.', 5, '08/17/2017');
update_reviews('Rangoli','Vivek T.',5,'09/17/2017');
update_reviews('Shanghai Inn','Audrey M.',2,'07/08/2017');
update_reviews('Cumin','Cameron J.', 2, '09/17/2017');
end;
/
select * from top5restaurants;
sqldeveloper outputs:
View BESTRATINGS_REST dropped.
View BESTRATINGS_REST created.
Table TOP5RESTAURANTS dropped.
Table TOP5RESTAURANTS created.
5 rows inserted.
View TOP5REST dropped.
View TOP5REST created.
Trigger TOP5_TRIGGER compiled
LINE/COL ERROR
7/5 PL/SQL: SQL Statement ignored
7/17 PL/SQL: ORA-00942: table or view does not exist
11/5 PL/SQL: SQL Statement ignored
11/17 PL/SQL: ORA-00942: table or view does not exist
18/5 PL/SQL: SQL Statement ignored
18/40 PL/SQL: ORA-00984: column not allowed here
Errors: check compiler log
You don't insert into a scalar variable. You can do a select into. The statement
select rid
into restname
from restaurant
where :new.rid = restaurant.rid;
is syntactically valid. But it is almost certainly incorrect. Presumably, you want to select the restaurant name not the rid
select name
into restname
from restaurant
where :new.rid = restaurant.rid;
If you declare a %rowtype variable, then you want to do a select * into that variable. Otherwise you'll get a compilation error in the future if anyone adds or removes a column. You'd have to add a predicate that specified which row you wanted to select. My guess is that you want something like this to give the row with the lowest best score (or the row with the lowest rid if there are two with the same low score
select *
into minrow
from top5rest low
where not exists( select 1
from top5rest high
where low.best > high.best )
and not exists( select 1
from top5rest same
where low.best = same.best
and low.rid > same.rid )
More fundamentally, though, even if you get your syntax errors corrected, you're going to get a runtime mutating table error if you try to query the rating table (which your view does) from inside a row-level trigger on the rating table. That's not allowed. It almost guarantees that you have a problem in your logic. In this case, there seems to be no need for a separate table to store the top 5 restaurants. Realistically, your view should just do that calculation if you need the results in real-time or you should create a materialized view that refreshes periodically if you don't need to see a restaurant's overall rating change instantly when new ratings are added. So you probably don't want a trigger at all.

Error with putting SELECT SUM into an IF statement

I encounter an error with code 1064 in my SQL statement but I cannot see where it is wrong.
I want to sum all the ETCS of all modules that a student have take part in. I have tried and the SELECT SUM statement is correct an return the sum.
However when I put it in an IF statement, error code 1064 is return.
The info on number of ETCS of each module is stored in table module_details.
The info of modules taken by student is stored in table student_module.
IF(SELECT SUM(module_etcs) AS total_etcs
FROM student_module
INNER JOIN module_details
ON student_module.module_id = module_details.module_id
WHERE student_module.student_id = '2222') = 10
THEN
INSERT INTO alumni_details(student_id,alumni_status)
VALUES('2222','S123');
END IF;
The value return by the SELECT SUM is 10.
But put in the IF statement cause error.

Error while using the select into statement

I was trying to use select into statement to copy contents from one table to another.
select* into xyz from xyz_123 where id = 100
but while executing I'm getting an error
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action:
Error at Line: 10 Column: 15
please help me fix this error
If table xyz already exists use this:
INSERT INTO xyz
SELECT * FROM xyz_123 WHERE id = 100
If table xyz does not yet exist, then create it:
CREATE TABLE xyz
AS SELECT * FROM xyz_123 WHERE id = 100
By the way, if you spend a little time searching Stack Overflow here, as well as one other site here, then you can piece this answer together yourself.
It is not correct syntax if you are executing it alone. Use like below.
insert into xyz
select * from xyz_123 where id = 100;

Postgres "missing FROM-clause entry" error on query with WITH clause

I am trying to use this query in Postgres 9.1.3:
WITH stops AS (
SELECT citation_id,
rank() OVER (ORDER BY offense_timestamp,
defendant_dl,
offense_street_number,
offense_street_name) AS stop
FROM consistent.master
WHERE citing_jurisdiction=1
)
UPDATE consistent.master
SET arrest_id = stops.stop
WHERE citing_jurisdiction=1
AND stops.citation_id = consistent.master.citation_id;
I get this error:
ERROR: missing FROM-clause entry for table "stops"
LINE 12: SET arrest_id = stops.stop
^
********** Error **********
ERROR: missing FROM-clause entry for table "stops"
SQL state: 42P01
Character: 280
I'm really confused. The WITH clause appears correct per Postgres documentation. If I separately run the query in the WITH clause, I get correct results.
From the fine manual:
There are two ways to modify a table using information contained in other tables in the database: using sub-selects, or specifying additional tables in the FROM clause.
So you just need a FROM clause:
WITH stops AS (
-- ...
)
UPDATE consistent.master
SET arrest_id = stops.stop
FROM stops -- <----------------------------- You missed this
WHERE citing_jurisdiction=1
AND stops.citation_id = consistent.master.citation_id;
The error message even says as much:
ERROR: missing FROM-clause entry for table "stops"
This can also happen if you mistype a table name. For example:
UPDATE profiles SET name = ( profile.first_name ) WHERE id = 1
Instead of profiles i incorrectly used profile !! This would work:
UPDATE profiles SET name = ( profiles.first_name ) WHERE id = 1