Combine Oracle CONTEXT index and function-based index - oracle

I have created the following PRODUCTS table in the Oracle 11g EE database:
( ID NUMBER(10) NOT NULL PRIMARY KEY
,NAME VARCHAR2(100) NOT NULL
,DESCRIPTION VARCHAR2(4000) NOT NULL
,CREATED DATE NOT NULL
,CHANGED DATE );
For this table, the following index of type CTXSYS.CONTEXT was created on the DESCRIPTION field:
BEGIN
CTX_DDL.CREATE_PREFERENCE ('MY_LEXER', 'BASIC_LEXER');
CTX_DDL.SET_ATTRIBUTE ('MY_LEXER', 'BASE_LETTER', 'YES');
END;
/
CREATE INDEX PROD_DESCR_TXT_IDX ON PRODUCTS(DESCRIPTION) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('LEXER MY_LEXER');
BEGIN
CTX_DDL.SYNC_INDEX('DOC_DESCR_TXT_IDX', '2M');
END;
/
ANALYZE TABLE DOCUMENTOS_GED COMPUTE STATISTICS;
This table has many thousands of rows, and I need to query the CONTEXT index to return the rows in descending order by the date of the last change (field CHANGED) and, if this field is null, by the date of creation (field CREATED).
I would like to know if anyone can help me create an index that meets the search criteria for CONTEXT and at the same time bring the results ordered by the "NVL (CHANGED, CREATED) DESC" function, in order to make the result of the following command instantaneous:
SELECT *
FROM PRODUCTS
WHERE CONTAINS (DESCRIPTION, 'kitchen AND accessories') > 0
ORDER BY NVL(CHANGED, CREATED) DESC;
Thanks in advance for your help

Related

PLSQL : Insert Result from Cursor into one column of plsql table

The following is my code To create a table object :
TYPE TempObjectsTable IS TABLE OF t_temp_objects%ROWTYPE
INDEX BY BINARY_INTEGER;
nt_scb_temp_objects TempObjectsTable;
The t_temp_objects has the following Columns defined :
Name Null? Type
-------------- ----- -------------
INVC_REF NUMBER
ORDERS NUMBER
ORDER_POS_TYPE NUMBER
RULE_CONDITION VARCHAR2(500)
CHARGE NUMBER
CURRENCY VARCHAR2(10)
TXN_DT DATE
Now, I have a cursor, which returns a lists of Orders, basically numbers.
CURSOR c_orders_frm_grp IS
select a.ordr_id from sa_order a
WHERE a.invc_ref is NULL
I am trying to add these to the plsql table created nt_scb_temp_objects above by using bulk collect. But i want the rest of the columns of nt_scb_temp_objects to filled as null for now, as i will be filling these columns as well in the coming steps.
Currently this is what i am trying.
IF c_orders_frm_grp %ISOPEN THEN
CLOSE c_orders_frm_grp ;
END IF;
OPEN c_orders_frm_grp;
FETCH c_orders_frm_grp BULK COLLECT INTO nt_scb_temp_objects.orders;
CLOSE c_orders_frm_grp;
And this is the error i get : Error(44,74): PLS-00302: component 'ORDERS' must be declared
You do not want that CURSOR and OPEN..FETCH constructs. Simply run a SELECT BULK COLLECT INTO
that collection.
DECLARE
TYPE TempObjectsTable IS TABLE OF t_temp_objects%ROWTYPE
INDEX BY BINARY_INTEGER;
nt_scb_temp_objects TempObjectsTable;
BEGIN
select a.ordr_id as ORDERS,
null as INVC_REF,
null as ORDER_POS_TYPE,
null as RULE_CONDITION,
null as CHARGE,
null as CURRENCY,
null as TXN_DT
BULK COLLECT INTO nt_scb_temp_objects from sa_order a
WHERE a.invc_ref is NULL ;
END;
/
DEMO
Why not use an INSERT INTO ... SELECT, and only specify the single column you want to populate now:
INSERT INTO TempObjectsTable(ORDERS)
SELECT ordr_id
FROM sa_order
WHERE invc_ref IS NULL;
In general you should avoid using cursors, as most regular database operations in SQL are already set based.
Note: If the temp table TempObjectsTable does not already exist, then you will have to create it.

Oracle- need to use CONTAINS to find a string that contains a period

I have a field in a table that is domain indexed so I can use CONTAINS in a query. I am trying to create a query that can find an acronym (i.e. J.A.V.A.) exactly. Problem is that the period '.' is a stopword that gets ignored. I need to figure out how to do this by escaping the '.' somehow. I can't find any reference online about how to do this, or maybe I am not fully understanding what I am reading.
I have tried
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J.A.V.A}')>0;
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J_A_V_A_}')>0;
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J\.A\.V\.A\.}')>0;
I created the domain index by:
CREATE INDEX table_txt_idx ON table(CLOB_column) INDEXTYPE IS CTXSYS.CONTEXT;
I saw something (https://oracle-base.com/articles/9i/full-text-indexing-using-oracle-text-9i) (https://docs.oracle.com/database/121/CCREF/csql.htm#CCREF0100) about appending to the index but I don't think it applies to a ctxsys index, but I am not fully sure. I just know what I used didn't work.
BEGIN
CTX_DLL.OPTIMIZE_INDEX('IDX_COLUMN_TXT','FAST');
END;
This didn't mention the ctxsys (https://docs.oracle.com/cd/B28359_01/text.111/b28303/ind.htm#BEIIEAFD)
I have created similar queries using LIKE and REGEXP_INSTR and need to create the same using CONTAINS so I can make sure I run the one that works the quickest.
SELECT * from table WHERE CLOB_column LIKE '%J.A.V.A.%'; --4.441 seconds
SELECT * from table WHERE REGEXP_INSTR(CLOB_column, '(J\.A\.V\.A\.)')>0; --23.528 seconds
Any reason you can't use LIKE?
CREATE TABLE suppliers
( supplier_id number(10) NOT NULL,
supplier_name varchar2(50) NOT NULL
);
INSERT INTO suppliers (supplier_id, supplier_name) VALUES (5000, 'Apple');
INSERT INTO suppliers (supplier_id, supplier_name) VALUES (5000, 'J.A.V.A');
SELECT * FROM suppliers WHERE supplier_name LIKE '%.%';
SELECT * FROM suppliers WHERE supplier_name LIKE 'J.A.V.A';

How to get the value of clob data which has date field and compare with timestamp in oracle

I have a table named masterregistry and it contains all the info and business logic in it and the data type of the colum is clob
desc master_registy:
id number not null,
name varchar2(100),
value clob
select value from master_registry where name='REG_DATE';
o/p
11-10-17
This date is common across all the business logic, I need to query my tables which has ,
desc get_employee
====================
id number not null,
first_name varchar2(100),
last_name varchar2(100),
last_mod_dt timestamp
Now I need to get all the values from the get_employee whose last_mod_dt should be greater than the value of master_registry where name='REG_DATE'.The value in the latter table is clob data, how to fetch and compare the date of a clob data against the timestamp from another table. Please help.
Maybe you need something like this.
SELECT *
FROM get_employee e
WHERE last_mod_dt > (SELECT TO_TIMESTAMP (TO_CHAR (VALUE), 'DD-MM-YY')
FROM master_registy m
WHERE m.id = e.id);
DEMO
Note that i have used the column value directly in TO_CHAR. You may have to use TRIM,SUBSTR or whatever required to get ONLY the date component.

create a table with additional null column in Oracle

I am trying to create a table and wrote following code
create table trial as(
SELECT l2_group AS Customer
, null AS Contact
FROM ACCT_MASKED_sep17_V1) ;
It's giving me an error when I run with create table where as select query runs.
How can I get the result
You need to specify a data type for that NULL column. For example:
create table t1 as
select 1 as c1
, cast(null as number) as c2
from dual
Table created.
If as a datatype for the NULL column you choose VARCHAR2(length) datatype, the length needs to be greater than 0.

Insertion in Nested Tables on Oracle DB

I am a new learner of PL/SQL databases,A kind of exercise given to apply database on apex.oracle.com with given sequence.Then I have created tables but when it comes to fill tables with the insertion code as follows,Application has given error,Would you mind if I need your assistance
Thanks in Advance,
CREATE TYPE TEMPORAL_VARCHAR AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART VARCHAR2(50)
);
CREATE TYPE TEMPORAL_NUMBER AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART NUMBER );
Time-related attributeshave defined with the code as follows;
CREATE TYPE NAME_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE ADDRESS_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE DEPARTMENT_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE MANAGER_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE SALARY_TYPE AS TABLE OF TEMPORAL_NUMBER;
CREATE TABLE EMPLOYEE (
SSN NUMBER primary key,
NAME NAME_TYPE,
ADDRESS ADDRESS_TYPE ,
BIRTH_DATE DATE,
MANAGER MANAGER_TYPE ,
DEPARTMENT DEPARTMENT_TYPE,
SALARY SALARY_TYPE
)
NESTED TABLE NAME STORE AS NAME_TABLE,
NESTED TABLE ADDRESS STORE AS ADDRESS_TABLE,
NESTED TABLE MANAGER STORE AS MANAGER_TABLE,
NESTED TABLE DEPARTMENT STORE AS DEPARTMENT_TABLE,
NESTED TABLE SALARY STORE AS SALARY_TABLE
;
And the insertion that I am inteded to do
INSERT INTO EMPLOYEE VALUES
(101,
NAME(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','James Brown')),
ADDRESS(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','BUCA, IZMIR')),
'23.10.1986',
MANAGER(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','Mike White')),
DEPARTMENT(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','DEPT_ID05')),
SALARY(TEMPORAL_NUMBER('23.11.2005',’12.31.9999’, 250000))
);
And the error message I recieved is :
ORA-00904: "SALARY": invalid identifier
There are spaces before _ here
CREATE TYPE MANAGER _TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE SALARY _TYPE AS TABLE OF TEMPORAL_NUMBER;
DEPARTMENT DEPARTMENT _TYPE
A comma is missing after DEPARTMENT _TYPE
try this solution:
'alter session set NLS_DATE_FORMAT='DD.MM.YYYY';'
----------------------------------------------------
INSERT INTO EMPLOYEE VALUES
(101,
NAME_TYPE(TEMPORAL_VARCHAR('23.10.1986','09.09.9999','James Brown')),
ADDRESS_TYPE(TEMPORAL_VARCHAR('15.12.2009','09.09.9999','BUCA')),
'23.10.1986',
MANAGER_TYPE(TEMPORAL_VARCHAR('24.05.2008','09.09.9999','Mike White')),
DEPARTMENT_TYPE(TEMPORAL_VARCHAR('03.01.2012','09.09.9999','DEPT_ID05')),
SALARY_TYPE(TEMPORAL_NUMBER('01.01.2003','09.09.9999', 3200))
);

Resources