AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 24531
Accepted
Adam Matan
Adam Matan
Asked: 2012-09-20 05:40:32 +0800 CST2012-09-20 05:40:32 +0800 CST 2012-09-20 05:40:32 +0800 CST

MySQL: Criar índice Se não existir

  • 772

Existe uma maneira de criar um índice no MySQL se ele não existir?

MySQL não suporta o formato óbvio:

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

A versão do MySQL ( mysql -V) é 5.1.48, mas acho que o MySQL não tem essa CREATE INDEX IF NOT EXISTcapacidade em todas as suas versões.

Qual é a maneira correta de criar um índice somente se ele ainda não existir no MySQL?

mysql index
  • 4 4 respostas
  • 146608 Views

4 respostas

  • Voted
  1. Best Answer
    RolandoMySQLDBA
    2012-09-20T07:12:05+08:002012-09-20T07:12:05+08:00

    Essa funcionalidade não existe. Há duas coisas a ter em mente:

    Crie o índice de qualquer maneira

    Você pode gerar o índice de forma que o índice seja criado sem verificar se o índice existe antecipadamente. Por exemplo, você pode executar o seguinte:

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

    Isso definitivamente criará dois índices sem verificação. Cada índice receberá um nome (talvez column_to_index,column_to_index_1). Claro, você está tentando evitar isso.

    Verifique o INFORMATION_SCHEMA primeiro

    Aqui está o layout de 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>
    

    Você pode apenas consultar a existência do índice pelo nome. Por exemplo, antes de executar

    CREATE INDEX index_name ON mytable(column);
    

    Você precisa correr

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

    Se IndexIsThere for 0, você poderá criar no índice. Talvez você possa escrever um procedimento armazenado para criar um índice na tabela de sua escolha.

    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 ;
    

    Aqui está um exemplo de execução (Ei, lembra desta tabela? É da pergunta que você fez em 27 de junho de 2012 ):

    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>
    

    De uma chance !!!

    • 69
  2. Mithun B
    2014-04-12T01:45:55+08:002014-04-12T01:45:55+08:00

    Eu tenho algo semelhante com o uso SELECT IF()da instrução no MySQL se você estiver tentando não ter procedimentos:

    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;
    

    Aqui o select iftem esse formato if (condition, true_case, false_case). O select 'index index_1 exists'é um caso fictício. E o _____desempenha o papel de nome de alias. Se o alias não for feito, o nome da coluna e a linha index index_1 existsserão exibidos, o que confundiria ainda mais. Para ser mais descritivo, você pode usar 'select ''index index_1 exists'' as _______;'.

    • 44
  3. the_nuts
    2019-07-18T05:24:38+08:002019-07-18T05:24:38+08:00

    Se você nomear o índice, a consulta falhará se o índice já existir (testado no MySQL 8.0):

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

    Código de erro: 1061. Nome de chave duplicado 'col_idx';

    Então você pode simplesmente pegar a exceção e ignorá-la, por exemplo em 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
        }
    }
    
    • 8
  4. Bennet Joseph
    2017-06-14T08:51:27+08:002017-06-14T08:51:27+08:00
    SELECT COUNT(*)
    FROM information_schema.statistics
    WHERE TABLE_SCHEMA = DATABASE()
      AND TABLE_NAME = 'table_name' 
      AND INDEX_NAME = 'index_name'; 
    

    Minha consulta lhe daria a contagem de índices presentes em uma tabela com um determinado index_name. Com base nessa contagem, você pode decidir se deve emitir um CREATE INDEXcomando ou não.

    Testado no MySQL versão 5.5 .

    MariaDB suporta IF NOT EXISTSsintaxe . Você pode usar CREATE INDEX IF NOT EXISTSlá.

    • 7

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve