not able to drop and recreate the oracle text index - sql

I am not able to drop and recreate the oracle text index.
SQL> drop index "WBR"."CTX_t1";
Index dropped
SQL>
SQL> CREATE INDEX "WBR"."CTX_t1"
2 ON WBR.t1(ASSET_XML)
3 INDEXTYPE IS "CTXSYS"."CONTEXT"
4 PARAMETERS ('DATASTORE CTXSYS.DIRECT_DATASTORE SECTION GROUP CTXSYS.AUTO_SECTION_GROUP SYNC (every "SYSDATE+10/1440")')
5 ;
CREATE INDEX "WBR"."CTX_t1"
ON WBR.t1(ASSET_XML)
INDEXTYPE IS "CTXSYS"."CONTEXT"
PARAMETERS ('DATASTORE CTXSYS.DIRECT_DATASTORE SECTION GROUP CTXSYS.AUTO_SECTION_GROUP SYNC(every "SYSDATE+10/1440")')
ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-20000: Oracle Text error:
DRG-10507: duplicate index name: CTX_t1
ORA-06512: at "CTXSYS.DRUE", line 160
ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 366
Even after dropping the cintext index, I can see the entry in CTXSYS.CTX_INDEXES.
The job and internal tables are still there in database:
DR$CTX_t1$I
DR$CTX_t1$J--job
DR$CTX_t1$K
DR$CTX_t1$N
DR$CTX_t1$R
DR$CTX_t1$X
any suggestions?

1) check if there exists an other object with the same name (possible case insensitive)
select owner, object_name, object_type from dba_objects where upper(object_name) like '%CTX_T1%';
if yes drop it.
2) try drop the index with the FORCE option
drop index "WBR"."CTX_t1" FORCE;
if it doesn't help:
3) contact Oracle support

it seems a bug on oracle. We have a script who refresh our quality database from the production database. To solve this problem, we execute this PL/SQL script before refresh begin.
/**
* Correctif bug sur la suppression d'index full text:
* Unable to recreate an Oracle Text index as the database continually throws a "DRG-10507: duplicate index name" error
* http://ask4dba.blogspot.com/2016/11/drg-10507-in-creating-text-index-after.html
* https://www.ibm.com/support/pages/unable-recreate-oracle-text-index-database-continually-throws-drg-10507-duplicate-index-name-error
**/
DECLARE
LR$IDX_ID NUMBER(15);
LR$IDX_NAME VARCHAR2(255);
LR$SCHEMA VARCHAR2(255);
CURSOR C1 IS
select IDX_ID, IDX_NAME, usr.USERNAME from CTXSYS.DR$INDEX
join all_users usr on usr.USER_ID = IDX_OWNER#
where IDX_NAME in ('IDX_EDI_EMISSION_MSG_EAI', 'IDX_EDI_EMISSION_MSG', 'IDX_EDI_RECEPTION_MSG', 'IDX_EDI_RECEPTION_MSG_TMS');
BEGIN
DBMS_OUTPUT.put_line('DEBUT de la suppression des index fulltext' );
OPEN C1;
LOOP
FETCH C1 INTO LR$IDX_ID, LR$IDX_NAME, LR$SCHEMA;
EXIT WHEN C1%NOTFOUND;
BEGIN
BEGIN
DBMS_OUTPUT.put_line('Suppression (drop) de l''index '|| LR$SCHEMA || '.' || LR$IDX_NAME );
execute immediate 'DROP INDEX ' || LR$SCHEMA || '.' || LR$IDX_NAME;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('Erreur Oracle #'||TO_CHAR(SQLCODE)||' : '||SQLERRM(SQLCODE));
DBMS_OUTPUT.put_line('L''index ' || LR$IDX_NAME ||' n''existe pas : ' || LR$IDX_ID);
END;
DBMS_OUTPUT.put_line('Suppression des lignes de l''index ' || LR$IDX_ID);
delete from ctxsys.dr$index_value where IXV_IDX_ID = LR$IDX_ID;
delete from ctxsys.dr$index_object where IXO_IDX_ID = LR$IDX_ID;
delete from ctxsys.dr$index where idx_id = LR$IDX_ID;
commit;
END;
END LOOP;
CLOSE C1;
COMMIT;
End ;
/

[1] Oracle Text: Create Or Alter Index Fails With DRG-50857, ORA-27486 ( Doc ID 2497828.1 )
grant create job to the user and then try to create the indexes, it should work.
I had a situation of changing index sync parameter from ('SYNC (on commit)') to ('SYNC (EVERY "SYSDATE+15/1440")'), as this will automatically use a Oracle job, the schema should have create job privilege.

it's not an answer basically, for those who get a slightly different error (i'm on Oracle 12c) during create index and right after drop index statements:
ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-20000: Oracle Text error:
DRG-50857: oracle error in drvxtab.create_index_tables
ORA-00955: name is already used by an existing object
ORA-06512: at "CTXSYS.DRUE", line 171
ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 316
there seems to be a time lag (or something else) between drop of the index, and the cleanup of the related data from the CTXSYS tables (but i didn't need any commit statements). so for me, executing drop of the index AGAIN and running the same create statement AGAIN resolved the issue (the second create runs OK)

Related

How to execute alter command within select statement in a loop in Oracle?

I am trying to Rebuild Indexes of a schema through a script but I am stucked at a point where I get the string ALTER INDEX OWNER.INDEX_NAME REBUILD NOLOGGING through select statement but I am not getting how to execute the alter command ,please guide :
I tried to assign str the value of select query used in 2nd for loop and then execute it but it gave error .
IS
STR VARCHAR2(5000);
BEGIN
FOR T IN (
SELECT USERNAME FROM DBA_USERS WHERE USERNAME ='REPORT'
)
LOOP
FOR CUR IN
(
SELECT ' ALTER INDEX '||OWNER||'.'||INDEX_NAME|| ' REBUILD NOLOGGING; ' FROM DBA_INDEXES
WHERE OWNER=T.USERNAME AND TEMPORARY='N'
)
LOOP
--- EXECUTE IMMEDIATE STR ;
INSERT INTO INDEX_REBUILD_HISTORY
SELECT DISTINCT OWNER, TRUNC(LAST_DDL_TIME) from DBA_OBJECTS where OBJECT_TYPE = 'INDEX'
AND
OWNER=T.USERNAME ;
COMMIT;
END LOOP;
END LOOP;
END ;
You use dynamic sql. And you don't need your outer loop. The filter on that is available in dba_indexes:
create procedure bld_idx
is
vsql varchar2(500);
for x in (select owner,
index_name
from dba_indexes
where owner = 'REPORT'
and TEMPORARY='N'
)
loop
vsql := ' ALTER INDEX '||x.OWNER||'.'||x.INDEX_NAME|| ' REBUILD NOLOGGING; ';
dbms_output.put_line(vsql); -- debugging only
execute immediate vsql;
end loop;
end;
Note 1: above is off the top of my head. There may be minor syntax issues, but if so you should be able to work them out.
Not 2: Rebuilding indexes is not something that needs to be done in the normal course of things. Richard Foote is probably the foremost authority on the internals of oracle indexes, and he has this to say: https://richardfoote.wordpress.com/2007/12/11/index-internals-rebuilding-the-truth/
"it gave error ." isn't helpful without the actual error you received. That said you've made the same mistake so many others do, you shouldn't include the ";" as part of your dynamic SQL - it's not part of the statement, it's only used by your client to know when to send code to the database.
FOR CUR IN
(
SELECT ' ALTER INDEX '||OWNER||'.'||INDEX_NAME|| ' REBUILD NOLOGGING' ddl_cmd FROM DBA_INDEXES
WHERE OWNER=T.USERNAME AND TEMPORARY='N'
)
...
EXECUTE IMMEDIATE CUR.ddl_cmd ;
(I've also given the column an alias so you can use it in your loop nicely.
Then
INSERT INTO INDEX_REBUILD_HISTORY
SELECT DISTINCT OWNER, TRUNC(LAST_DDL_TIME) from DBA_OBJECTS where OBJECT_TYPE = 'INDEX'
AND
OWNER=T.USERNAME ;
Is not filtering on the index you just rebuilt, it doesn't seem like it's going to get entirely useful information.
That said...
Is it really worth rebuilding all your indexes offline and making them unrecoverable? Probably not, if you're doing this more than once and are benefiting then there's probably something that could be changed with your data model to help. Have a good read of this presentation by Richard Foote, a well established Oracle Indexing Expert https://richardfoote.files.wordpress.com/2007/12/index-internals-rebuilding-the-truth.pdf I doubt you'd come away from it believing that rebuilding all the indexes is a solution.

Executing a PostgreSQL query with an EXCEPTION results in two different ERROR messages

I have an PostgreSQL query that includes a transaction and an exception if a column is duplicated:
BEGIN;
ALTER TABLE "public"."cars"
ADD COLUMN "top_speed" text;
EXCEPTION WHEN duplicate_column THEN NOTHING;
ROLLBACK;
In this query I am trying to add a column that already exists (playing a little bit with exceptions) and if it does then the query shall just ignore it. At the moment I am not really sure if the exception-code I am using is the right (couldn't find a site where they are described; only found this)
My Problem is if I execute this query I get the error-message:
ERROR: column "top_speed" of relation "cars" already exists
And if I execute it a second time the error-message changes to:
ERROR: current transaction is aborted, commands ignored until end of transaction block
Try an anonymous code block. As Laurenz mentioned, you were mixing PL/pgSQL and SQL commands.
Sample table
CREATE TABLE t (f1 TEXT);
Anonymous code block
DO $$
BEGIN
IF (SELECT count(column_name) FROM information_schema.columns
WHERE table_schema = 'public' AND
table_name = 't' AND
column_name = 'f2') = 0 THEN
ALTER TABLE public.t ADD COLUMN "f2" text;
END IF;
END$$;
After execution you have your new column. If the column already exists, it will do nothing.
SELECT * FROM t;
f1 | f2
----+----
0 Zeilen
In PostgreSQL 9.6+ you can use IF NOT EXISTS to check if a given column already exists in the table before creating it:
ALTER TABLE t ADD COLUMN IF NOT EXISTS f2 TEXT;
Code at db<>fiddle

Oracle SQL commands that work when executed separately does not work when executed together. Why?

This is regarding a migration script. The required migration can be done by using 4 separate SQL commands. However, when they are combined to run as a script I am getting PLS-00103: Encountered the symbol error.
These are the SQL commands that I've used to do the migration. The table will have a PK which is a composite key of 3 columns in the table. First I need to remove the constraint, then add a new column called ID to that table, make it auto incremental by adding a sequence and then make it the new PK of the table.
Following commands work and does the exact job when I execute them one by one.
BEGIN
FOR item IN (
SELECT *
FROM all_constraints
WHERE table_name = 'TEST_DB_CHANGE'
)
LOOP
EXECUTE immediate 'ALTER TABLE TEST_DB_CHANGE DROP CONSTRAINT ' || item.CONSTRAINT_NAME;
END LOOP;
END;
/
BEGIN
EXECUTE IMMEDIATE 'CREATE SEQUENCE TEST_DB_CHANGE_SEQUENCE START WITH 1 INCREMENT BY 1 nomaxvalue';
END;
/
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE TEST_DB_CHANGE ADD (ID NUMBER DEFAULT TEST_DB_CHANGE_SEQUENCE.nextval)';
END;
/
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE TEST_DB_CHANGE ADD CONSTRAINT TEST_DB_CHANGE_PK PRIMARY KEY (ID)';
END;
But when they are executed together I get the following error.
*Query execution failed
Reason:
SQL Error [6550] [65000]: ORA-06550: line 11, column 1:
PLS-00103: Encountered the symbol "/" *
I tried removing the "/" from that line, from every line, from every line except the last line, but none of that fixed the issue. Then the error will change to:
Reason:
SQL Error [6550] [65000]: ORA-06550: line 12, column 1:
PLS-00103: Encountered the symbol "BEGIN"
What am I doing wrong here?
I don't know how you have combined them but it should be:
BEGIN
FOR item IN (
SELECT *
FROM all_constraints
WHERE table_name = 'TEST_DB_CHANGE'
)
LOOP
EXECUTE immediate 'ALTER TABLE TEST_DB_CHANGE DROP CONSTRAINT ' || item.CONSTRAINT_NAME;
END LOOP;
EXECUTE IMMEDIATE 'CREATE SEQUENCE TEST_DB_CHANGE_SEQUENCE START WITH 1 INCREMENT BY 1 nomaxvalue';
EXECUTE IMMEDIATE 'ALTER TABLE TEST_DB_CHANGE ADD (ID NUMBER DEFAULT TEST_DB_CHANGE_SEQUENCE.nextval)';
EXECUTE IMMEDIATE 'ALTER TABLE TEST_DB_CHANGE ADD CONSTRAINT TEST_DB_CHANGE_PK PRIMARY KEY (ID)';
END;

oracle reentrant alter table

I have an SQL script to execute multiple times (must be reentrant).
One of the script line is
alter table MATABLE modify (MADATA null);
This commands works well when the 'not null' constraint for column MADATA of table MATABLE is effectively removed. But the second time, I got an error, example:
Erreur SQL : ORA-01451: colonne à modifier en non renseignée (NULL) ne peut être passée à NULL
01451. 00000 - "column to be modified to NULL cannot be modified to NULL"
That's because the constraint was already removed by the first execution and no more exist.
How to execute this same script without error ?
maybe through PL/SQL Script ?
You can use the data dictionary view user_tab_cols to check the table before doing the update.
declare
lCount number;
begin
select count(*) into lCount from user_tab_cols
where table_name = 'MATABLE'
and column_name = 'MADATA'
and nullable = 'N';
if (lCount = 1) then
execute immediate 'alter table MATABLE modify (MADATA null)';
end if;
end;
Note that user_tab_cols only contains the information about tables in the same schema as the logged on user. If you are modifying tables of another user, you can user all_tab_cols or dba_tab_cols.
Another option would be to use an exception handler and just throw away the exception, like this:
begin
execute immediate 'alter table MATABLE modify (MADATA null)';
exception
when others then
null;
end;
It is normal behavior.
It can happen in two scenarios :
1) If your field column is a constraint
2) if you've already defined the field column as allowing NULL values.

Informatica pre sql to drop an index

I am trying to load 2 million records into a oracle table using the Oracle external loader in Informatica. In order to load the data, I am trying to drop the index on the table and re create after the data is loaded. I am using the below anonymous block in the pre SQL in mapping for the target:
Declare indxcnt int\;
BEGIN
SELECT COUNT(INDEX_NAME)
INTO indxcnt
FROM all_INDEXES WHERE INDEX_NAME = 'TEST_INDEX1'\;
IF indxcnt > 0 THEN
Execute Immediate 'DROP INDEX TEST_INDEX1'\;
END If \;
END\;
However the pre SQL is not working and as the index is not getting dropped.
When I use the same anonymous block in the session properties using the relation writer, it is working fine.
Kindly help me how to drop and re create the index while using the loader to load the table.
At the end of the software you want to execute. You can do it by /:
This is in PL/SQL. I don't know informatica but perhaps this could help you.
DECLARE
indxcnt NUMBER;
BEGIN
--
SELECT COUNT(INDEX_NAME)
INTO indxcnt
FROM all_indexes WHERE index_name = 'TEST_INDEX1';
--
IF indxcnt > 0
THEN
EXECUTE IMMEDIATE 'DROP INDEX TEST_INDEX1';
END IF;
END;
/