it-swarm.com.de

MySQL: Index erstellen Wenn nicht vorhanden

Gibt es eine Möglichkeit, einen Index in MySQL zu erstellen, wenn dieser nicht vorhanden ist?

MySQL unterstützt das offensichtliche Format nicht:

CREATE INDEX IF NOT EXISTS index_name ON table(column)
ERROR 1064 (42000): You have an error in your SQL syntax;...

Die MySQL-Version (mysql -V) Ist 5.1.48, aber ich denke, dass MySQL in allen Versionen nicht über die CREATE INDEX IF NOT EXIST - Fähigkeit verfügt.

Wie kann ein Index nur dann richtig erstellt werden, wenn er in MySQL noch nicht vorhanden ist?

67
Adam Matan

Diese Funktionalität existiert nicht. Es gibt zwei Dinge zu beachten:

Erstellen Sie den Index trotzdem

Sie können den Index so generieren, dass der Index erstellt wird, ohne zu überprüfen, ob der Index im Voraus vorhanden ist. Sie können beispielsweise Folgendes ausführen:

ALTER TABLE table_name ADD INDEX (column_to_index);
ALTER TABLE table_name ADD INDEX (column_to_index);

Dadurch werden definitiv zwei Indizes ohne Überprüfung erstellt. Jedem Index wird ein Name zugewiesen (möglicherweise column_to_index, column_to_index_1). Natürlich versuchen Sie das zu vermeiden.

Überprüfen Sie zuerst INFORMATION_SCHEMA

Hier ist das Layout von INFORMATION_SCHEMA.STATISTICS:

mysql> show create table statistics\G
*************************** 1. row ***************************
       Table: STATISTICS
Create Table: CREATE TEMPORARY TABLE `STATISTICS` (
  `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  `NON_UNIQUE` bigint(1) NOT NULL DEFAULT '0',
  `INDEX_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `INDEX_NAME` varchar(64) NOT NULL DEFAULT '',
  `SEQ_IN_INDEX` bigint(2) NOT NULL DEFAULT '0',
  `COLUMN_NAME` varchar(64) NOT NULL DEFAULT '',
  `COLLATION` varchar(1) DEFAULT NULL,
  `CARDINALITY` bigint(21) DEFAULT NULL,
  `SUB_PART` bigint(3) DEFAULT NULL,
  `PACKED` varchar(10) DEFAULT NULL,
  `NULLABLE` varchar(3) NOT NULL DEFAULT '',
  `INDEX_TYPE` varchar(16) NOT NULL DEFAULT '',
  `COMMENT` varchar(16) DEFAULT NULL,
  `INDEX_COMMENT` varchar(1024) NOT NULL DEFAULT ''
) ENGINE=MEMORY DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

Sie können die Existenz des Index nur nach Namen abfragen. Zum Beispiel, bevor Sie laufen

CREATE INDEX index_name ON mytable(column);

Du musst rennen

SELECT COUNT(1) IndexIsThere FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema=DATABASE() AND table_name='mytable' AND index_name='index_name';

Wenn IndexIsThere 0 ist, können Sie im Index erstellen. Vielleicht können Sie eine gespeicherte Prozedur schreiben, um einen Index für die Tabelle Ihrer Wahl zu erstellen.

DELIMITER $$

DROP PROCEDURE IF EXISTS `adam_matan`.`CreateIndex` $$
CREATE PROCEDURE `adam_matan`.`CreateIndex`
(
    given_database VARCHAR(64),
    given_table    VARCHAR(64),
    given_index    VARCHAR(64),
    given_columns  VARCHAR(64)
)
BEGIN

    DECLARE IndexIsThere INTEGER;

    SELECT COUNT(1) INTO IndexIsThere
    FROM INFORMATION_SCHEMA.STATISTICS
    WHERE table_schema = given_database
    AND   table_name   = given_table
    AND   index_name   = given_index;

    IF IndexIsThere = 0 THEN
        SET @sqlstmt = CONCAT('CREATE INDEX ',given_index,' ON ',
        given_database,'.',given_table,' (',given_columns,')');
        PREPARE st FROM @sqlstmt;
        EXECUTE st;
        DEALLOCATE PREPARE st;
    ELSE
        SELECT CONCAT('Index ',given_index,' already exists on Table ',
        given_database,'.',given_table) CreateindexErrorMessage;   
    END IF;

END $$

DELIMITER ;

Hier ist ein Beispiellauf (Hey, erinnerst du dich an diese Tabelle? Es ist von die Frage, die du am 27. Juni 2012 gestellt hast ):

mysql> show create table pixels\G
*************************** 1. row ***************************
       Table: pixels
Create Table: CREATE TABLE `pixels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(30) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `pixel_data` blob,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> call createindex('adam_matan','pixels','type_timestamp_id_ndx','type,timestamp,id');
Query OK, 0 rows affected (0.20 sec)

mysql> show create table pixels\G
*************************** 1. row ***************************
       Table: pixels
Create Table: CREATE TABLE `pixels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(30) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `pixel_data` blob,
  PRIMARY KEY (`id`),
  KEY `type_timestamp_id_ndx` (`type`,`timestamp`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> call createindex('adam_matan','pixels','type_timestamp_id_ndx','type,timestamp,id');
+-----------------------------------------------------------------------+
| CreateindexErrorMessage                                               |
+-----------------------------------------------------------------------+
| Index type_timestamp_id_ndx Already Exists on Table adam_matan.pixels |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql>

Versuche es !!!

40
RolandoMySQLDBA

Ich habe etwas Ähnliches mit der Verwendung der Anweisung SELECT IF() in MySQL, wenn Sie versuchen, keine Prozeduren zu haben:

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;

Hier hat select if Dieses Format if (condition, true_case, false_case). Der select 'index index_1 exists' Ist ein Dummy-Fall. und _____ spielt die Rolle des Aliasnamens. Wenn kein Alias ​​erstellt wird, zeigen sowohl der Spaltenname als auch die Zeile index index_1 exists, Was noch mehr verwirrt. Zur besseren Beschreibung können Sie 'select ''index index_1 exists'' as _______;' verwenden.

39
Mithun B

Wenn Sie den Index benennen, schlägt die Abfrage fehl, wenn der Index bereits vorhanden ist (getestet in MySQL 8.0):

ALTER TABLE `my_table` ADD INDEX `col_idx` (`col` DESC);

Fehlercode: 1061. Doppelter Schlüsselname 'col_idx';

Sie können die Ausnahme also einfach abfangen und ignorieren, beispielsweise in PHP:

try {
    $db->query('ALTER TABLE `my_table` ADD INDEX `col_idx` (`col` DESC) VISIBLE;');
} catch (PDOException $ex) {
    if($exception->errorInfo[2] == 1061) {
        // Index already exists
    } else {
        // Another error occurred
    }
}
6
the_nuts
SELECT COUNT(*)
FROM information_schema.statistics
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'table_name' 
  AND INDEX_NAME = 'index_name'; 

Meine Abfrage würde Ihnen die Anzahl der Indizes geben, die in einer Tabelle mit einem bestimmten Indexnamen vorhanden sind. Anhand dieser Anzahl können Sie entscheiden, ob Sie einen CREATE INDEX - Befehl ausgeben möchten oder nicht.

Getestet mit MySQL Version 5.5 .

MariaDB unterstützt IF NOT EXISTS Syntax . Sie können dort CREATE INDEX IF NOT EXISTS Verwenden.

4
Bennet Joseph