it-swarm.com.de

Wie kann ich "wenn vorhanden" zum Erstellen oder Löschen eines Index in MySQL einsetzen?

Ich habe mich gefragt, ob es eine Möglichkeit gibt, zu überprüfen, ob ein Index vorhanden ist, bevor er erstellt oder in MySQL zerstört wird. Anscheinend gab es vor einigen Jahren eine Anfrage für dieses Feature, aber ich kann keine Dokumentation für eine Lösung finden. Dies muss in einer PHP -App mit MDB2 durchgeführt werden.

49
Paul

Hier ist mein 4er Liner:

set @exist := (select count(*) from information_schema.statistics where table_name = 'table' and index_name = 'index' and table_schema = database());
set @sqlstmt := if( @exist > 0, 'select ''INFO: Index already exists.''', 'create index i_index on tablename ( columnname )');
PREPARE stmt FROM @sqlstmt;
EXECUTE stmt;
41
Nikhil S

Der Code IF EXISTS ist noch nicht für DROP INDEX oder CREATE INDEX erstellt. Sie können jedoch manuell die Existenz prüfen, bevor Sie einen Index erstellen/löschen.

Verwenden Sie diesen Satz, um zu prüfen, ob der Index bereits existiert.

SHOW INDEX FROM table_name WHERE KEY_NAME = 'index_name'
  • Wenn die Abfrage Null (0) zurückgibt, ist der Index nicht vorhanden, und Sie können ihn erstellen.
  • Wenn die Abfrage eine positive Zahl zurückgibt, ist der Index vorhanden, und Sie können ihn löschen.
23
Pablo Venturino

Hier ist ein DROP INDEX IF EXISTS-Verfahren:

DELIMITER $$

DROP PROCEDURE IF EXISTS drop_index_if_exists $$
CREATE PROCEDURE drop_index_if_exists(in theTable varchar(128), in theIndexName varchar(128) )
BEGIN
 IF((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name =
theTable AND index_name = theIndexName) > 0) THEN
   SET @s = CONCAT('DROP INDEX ' , theIndexName , ' ON ' , theTable);
   PREPARE stmt FROM @s;
   EXECUTE stmt;
 END IF;
END $$

DELIMITER ;

Dieser Code wurde basierend auf der folgenden Prozedur erstellt: Bestimmen, ob der MySQL-Tabellenindex vor dem Erstellen von existiert

11
Datageek

Ich habe die hier gefundenen Antworten angepasst und wo sonst die folgenden Sprocs zum Ablegen und Erstellen von Indizes gefunden. Beachten Sie, dass der AddTableIndex-Sproc den Index bei Bedarf löschen kann. Sie akzeptieren auch einen Schemanamen, der für meine Verwendung kritisch war.

DELIMITER //

DROP PROCEDURE IF EXISTS migrate.DropTableIndex //

CREATE PROCEDURE migrate.DropTableIndex
    (
        in schemaName varchar(128) -- If null use name of current schema;
        , in tableName varchar(128) -- If null an exception will be thrown.
        , in indexName varchar(128) -- If null an exception will be thrown.
    )
BEGIN
    SET schemaName = coalesce(schemaName, schema());
    IF((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = schemaName and table_name = tableName AND index_name = indexName) > 0) THEN
        SET @s = CONCAT('DROP INDEX `' , indexName , '` ON `' , schemaName, '`.`', tableName, '`');
        PREPARE stmt FROM @s;
        EXECUTE stmt;
    END IF;
END //

DROP PROCEDURE IF EXISTS migrate.AddTableIndex//

CREATE PROCEDURE migrate.AddTableIndex
    ( 
        IN schemaName varchar(128) -- If null use name of current schema;
        , IN tableName varchar(128) -- If null an exception will be thrown.
        , IN indexName varchar(128) -- If null an exception will be thrown.
        , IN indexDefinition varchar(1024) -- E.g. '(expireTS_ ASC)'
        , IN ifPresent ENUM('leaveUnchanged', 'dropAndReplace') -- null=leaveUnchanged.
        , OUT outcome tinyint(1) -- 0=unchanged, 1=replaced, 4=added.
    )
    BEGIN

    DECLARE doDrop tinyint(1) DEFAULT NULL;
    DECLARE doAdd tinyint(1) DEFAULT NULL;
    DECLARE tmpSql varchar(4096) DEFAULT '';

    SET schemaName = coalesce(schemaName, schema());
    SET ifPresent = coalesce(ifPresent, 'leaveUnchanged');
    IF EXISTS (SELECT * FROM   INFORMATION_SCHEMA.STATISTICS WHERE  table_schema = schemaName AND table_name = tableName AND index_name = indexName) THEN
        IF (ifPresent = 'leaveUnchanged') THEN
            SET doDrop = 0;
            SET doAdd = 0;
            SET outcome = 0;
            ELSEIF (ifPresent = 'dropAndReplace')
            THEN
            SET doDrop = 1;
            SET doAdd = 1;
            SET outcome = 1;
        END IF;
    ELSE
        SET doDrop = 0;
        SET doAdd = 1;
        SET outcome = 4;
    END IF;

    IF (doDrop = 1) THEN
        SET tmpSql = concat( 'alter table `', schemaName, '`.`', tableName, '` drop index `', indexName, '` ');
        SET @sql = tmpSql;
        PREPARE tmp_stmt FROM @sql;
        EXECUTE tmp_stmt;
        DEALLOCATE PREPARE tmp_stmt;
    END IF;

    IF (doAdd = 1) THEN
        SET tmpSql = concat( 'alter table `', schemaName, '`.`', tableName, '` add index `', indexName, '` (', indexDefinition, ')');
        SET @sql = tmpSql;
        PREPARE tmp_stmt FROM @sql;
        EXECUTE tmp_stmt;
        DEALLOCATE PREPARE tmp_stmt;
    END IF;

    END;
//

DELIMITER ;
2
Thomas Paine

Ich habe etwas Ähnliches mit der Anweisung SELECT IF () in MySQL.

select if (
    exists(
        select distinct index_name from information_schema.statistics 
        where table_schema = 'schema_db_name' 
        and table_name = 'tab_name' and index_name like 'index_1'
    )
    ,'select ''index index_1 exists'' _______;'
    ,'create index index_1 on tab_name(column_name_names)') into @a;
PREPARE stmt1 FROM @a;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

Der Vorteil der if () - Anweisung ist, dass keine Prozeduren geschrieben werden müssen.

1
Mithun B

MySQL Workbench Version 6.3 (MySql-Gabel MariaDb)

DROP INDEX IF EXISTS FK_customer__client_school__school_id ON dbname.tablename;
1
SushiGuy

Ich denke, das wird hilfreich sein, um Ihren bestehenden Index zu löschen.

        DELIMITER //
        CREATE PROCEDURE dropIndexing
        ()
        BEGIN

        IF EXISTS(
                    SELECT * FROM information_schema.statistics 
                    WHERE TABLE_SCHEMA = DATABASE() 
                    AND `table_name`='mytable' 
                    AND `index_name` = 'myindex'
                )
        THEN
        ALTER TABLE `mytable` DROP INDEX `myindex`;
        END IF;

        END //
        DELIMITER ;

        CALL dropIndexing();
        DROP PROCEDURE dropIndexing;
0
jeewiya

Ich hatte Probleme mit einigen der hier vorgestellten Lösungen. Das ist was ich mir ausgedacht habe:

DELIMITER $$

DROP PROCEDURE IF EXISTS myschema.create_index_if_not_exists $$
CREATE PROCEDURE myschema.create_index_if_not_exists(in p_tableName VARCHAR(128), in p_indexName VARCHAR(128), in p_columnName VARCHAR(128) )
BEGIN

PREPARE stmt FROM 'SELECT @indexCount := COUNT(1) from information_schema.statistics WHERE `table_name` = ? AND `index_name` = ?';
SET @table_name = p_tableName;
SET @index_name = p_indexName;
EXECUTE stmt USING @table_name, @index_name;
DEALLOCATE PREPARE stmt;

-- select @indexCount;

IF( @indexCount = 0 ) THEN
  SELECT 'Creating index';
  SET @createIndexStmt = CONCAT('CREATE INDEX ', p_indexName, ' ON ', p_tableName, ' ( ', p_columnName ,')');
  PREPARE stmt FROM @createIndexStmt;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END IF;

END $$

DELIMITER ;

Verwenden Sie es wie folgt:

call myschema.create_index_if_not_exists('MyTable','end_time_index','end_time');

Dies wurde unter Mac OS X 10.8.2 mit MySQL 5.5.24 und unter Windows 7 mit MySQL 5.5.21 getestet

0
Wim Deblauwe

Hier ist eine Problemumgehung für den DROP INDEX IF EXISTS, der in MySQL- und MariaDB-Versionen vor v10.1.4 fehlt. Sie können es auch für jede andere Anweisung verwenden, die Sie möchten. Dies sollte von der Existenz eines INDEX abhängen (z. B. für SELECT "info: index exists." wie im folgenden Beispiel).

-- DROP INDEX IF EXISTS
SELECT
    COUNT(*)
INTO
    @INDEX_my_index_ON_TABLE_my_table_EXISTS
FROM
    `information_schema`.`statistics`
WHERE
    `table_schema` = 'my_database'
    AND `index_name` = 'my_index'
    AND `table_name` = 'my_table'
;
SET @statement := IF(
    @INDEX_my_index_ON_TABLE_my_table_EXISTS > 0,
    -- 'SELECT "info: index exists."',
    'DROP INDEX `my_index` ON `my_table`',
    'SELECT "info: index does not exist."'
);
PREPARE statement FROM @statement;
EXECUTE statement;
0
automatix