oracle删除索引(如果存在)

oracle删除索引(如果存在),oracle,indexing,Oracle,Indexing,如何仅在索引存在时删除它 这看起来很简单,但我确实在网上找到了任何东西。 我们的想法是只有当它存在时才删除它,因为如果它不存在,我将有一个错误,我的进程将停止 我找到这个来查找索引是否存在: select index_name from user_indexes where table_name = 'myTable' and index_name='myIndexName' 但我不知道如何把它和 DROP INDEX myIndexName 在Oracle中,不能同时使用DDL和DML。为

如何仅在索引存在时删除它

这看起来很简单,但我确实在网上找到了任何东西。 我们的想法是只有当它存在时才删除它,因为如果它不存在,我将有一个错误,我的进程将停止

我找到这个来查找索引是否存在:

select index_name
from user_indexes
where table_name = 'myTable'
and index_name='myIndexName'
但我不知道如何把它和

DROP INDEX myIndexName

在Oracle中,不能同时使用DDL和DML。为了做到这一点,您需要围绕语句进行操作

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;
因此,首先检查索引是否存在

其次,通过executeimmediate语句删除索引

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;
这段代码是我脑子里想不出来的,你可能需要稍微修改一下,但这给了我一个想法


希望这有帮助!=)

不要检查是否存在。尝试删除,并在必要时捕获异常

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;
/

我创建了一个过程,以便可以多次调用它:

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 ;
现在可以多次调用它:

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

我希望这会有所帮助。它是所有解决方案的组合:) 顺便说一下,谢谢你的帮助

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;

@塞缪尔的解决方案是最正确的。这是应该被接受的。当心DDL命令的隐式提交!!不管你喜欢与否,这一点都是肯定的。如果有必要,将其封装到一个自治事务中。没有直接解决方案的原因是不应该出现这种情况。这是一个配置管理问题。@APC这是理想世界和我们的世界之间的区别。在这种情况下,你不得不做一些“不应该做的”事情。有时候,这是因为以前有人做了一个错误的决定。有时,这是因为情况发生了变化,突然做出了一个在当时是好的选择,而不是坏的选择。在我看来,“它不应该发生”从来都不是遗漏某个特性的有效理由。这可能是在更重要的问题上分配资源的一个有效理由,但其他几种数据库技术提供了类似于
如果存在则删除
,我很欣赏它的存在。当然,“删除索引”已经检查了索引的存在,所以您现在要做两次。这种技术引入了竞争条件。请考虑使用@塞缪尔提供的答案。我已经提醒用户,我接受的答案有竞争条件。我建议使用@Samuel提供的答案。我不能删除我的答案,因为它已在2010年被接受,而不是
删除过程
您可以使用
创建或替换过程
与接受的答案相比,这有什么优势,除了您可能可以将
计数
替换为
存在
?@jpmc26接受的答案具有竞争条件。索引可能被放在检查计数的行和执行立即数的行之间。@Samuel虽然这是一个有效点,但我希望人们不会有两个独立的命令试图同时对同一对象执行DDL。;)欢迎来到多线程世界:(很好的回答+1您忽略了这里的所有例外情况,这绝对不是一个好的做法。