2010-04-27 7 views
23

¿Cómo se puede soltar un índice solo si existe?índice de caída de oráculo si existe

Parece simple pero encontré cualquier cosa en la red. La idea es soltarlo solo si existe, porque si no, tendré un error y mi proceso se detendrá.

He encontrado esto para encontrar si existe el índice:

select index_name 
from user_indexes 
where table_name = 'myTable' 
and index_name='myIndexName' 

Pero no sé cómo ponerlo junto con

DROP INDEX myIndexName 
+3

@ Samuel es la solución más correcta. En mi humilde opinión, ese es el que debería haber sido aceptado. –

+0

¡Cuidado con los comandos implícitos de DDL! Esa gota se compromete, guste o no. Envuélvalo en una transacción autónoma si es necesario. – Samuel

+1

La razón por la cual no hay una solución directa es porque la situación no debería surgir. Este es un problema de gestión de la configuración. – APC

Respuesta

27
DECLARE 
    COUNT_INDEXES INTEGER; 
BEGIN 
    SELECT COUNT(*) INTO COUNT_INDEXES 
    FROM USER_INDEXES 
    WHERE INDEX_NAME = 'myIndexName'; 

    IF COUNT_INDEXES > 0 THEN 
    EXECUTE IMMEDIATE 'DROP INDEX myIndexName'; 
    END IF; 
END; 
/
+3

Por supuesto, "DROP INDEX" * ya * verifica la existencia del índice, por lo que lo hace dos veces. –

1

En Oracle, no se puede mezclar DDL y DML. Para hacerlo, debe solucionarlo con la instrucción EXECUTE IMMEDIATE.

Por lo tanto, primero compruebe la existencia del índice.

En segundo lugar, suelte el índice a través de la instrucción EXECUTE INMEDIATA.

DECLARE v_Exists NUMBER; 

BEGIN 
    v_Exists := 0; 

    SELECT 1 INTO v_Exists 
     FROM USER_INDEXES 
     WHERE TABLE_NAME LIKE 'myTable' 
      AND INDEX_NAME LIKE 'myIndexName' 

    IF v_Exists = 1 THEN 
     EXECUTE IMMEDIATE "DROP INDEX myIndexName" 
    ENDIF; 

    EXCEPTION 
     WHEN OTHERS THEN 
      NULL; 
END; 

Este código está fuera de mi cabeza y es posible que tengas que arreglarlo un poco, pero esto da una idea.

Espero que esto ayude! =)

56

No verifique la existencia. Trate de bajar y capturar la excepción si es necesario ...

declare 
index_not_exists EXCEPTION; 
PRAGMA EXCEPTION_INIT(index_not_exists, -1418); 
begin 

    execute immediate 'drop index foo'; 
exception 
    when index_not_exists then null; 
end; 
/
+1

¿Qué ventaja sobre la respuesta aceptada tiene esto, aparte del hecho de que probablemente podría reemplazar 'COUNT' con' EXISTS'? – jpmc26

+2

@ jpmc26 La respuesta aceptada tiene una condición de carrera. El índice podría haberse descartado entre la línea que verifica el recuento y la ejecución inmediata. – Samuel

+0

@Samuel Si bien ese es un punto válido, espero que la gente no tenga 2 comandos independientes tratando de ejecutar DDL en el mismo objeto al mismo tiempo. ;) – jpmc26

0

Hice un procedimiento para que pueda ser llamado varias veces:

DELIMITER €€ 
DROP PROCEDURE IF EXISTS ClearIndex€€ 
CREATE PROCEDURE ClearIndex(IN var_index VARCHAR(255),IN var_table VARCHAR(255)) 
BEGIN 
    SET @temp = concat('DROP INDEX ', var_index, ' ON ', var_table); 
    PREPARE stm1 FROM @temp; 
    BEGIN 
     DECLARE CONTINUE HANDLER FOR 1091 SELECT concat('Index ', var_index,' did not exist in ',var_table,', but was handled') AS 'INFO'; 
      EXECUTE stm1; 
    END; 
END €€ 
DELIMITER ; 

Ahora se le puede llamar más de una vez:

CALL ClearIndex('employees_no_index','employees'); 
CALL ClearIndex('salaries_no_index','salaries'); 
CALL ClearIndex('titles_no_index','titles'); 
+0

En lugar de 'DROP PROCEDURE' puede usar' CREATE OR REPLACE PROCEDURE' – psur

0

Espero que esto ayude. Es una combinación de todas las soluciones :) ¡Por cierto gracias por la ayuda!

CREATE OR REPLACE PROCEDURE CLEAR_INDEX(INDEX_NAME IN VARCHAR2) AS 
BEGIN 
    EXECUTE IMMEDIATE 'drop index ' || INDEX_NAME; 
EXCEPTION 
    WHEN OTHERS THEN 
     NULL; 
END CLEAR_INDEX;