La guía o código que hallarás en este post es la solución más sencilla y válida que encontramos a esta duda o problema.
Solución:
Esa funcionalidad no existe. Hay dos cosas a tener en cuenta:
Crear el índice de todos modos
Puede generar un índice de tal manera que el índice se cree sin verificar que el índice exista antes de tiempo. Por ejemplo, puede ejecutar lo siguiente:
ALTER TABLE table_name ADD INDEX (column_to_index);
ALTER TABLE table_name ADD INDEX (column_to_index);
Esto definitivamente creará dos índices sin verificar. A cada índice se le asignará un nombre (quizás columna_a_índice, columna_a_índice_1). Por supuesto, usted está tratando de evitar eso.
Verifique INFORMACION_ESQUEMA primero
Aquí está el diseño de INFORMATION_SCHEMA.STATISTICS:
mysql> show create table statisticsG
*************************** 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>
Simplemente podría consultar la existencia del índice por nombre. Por ejemplo, antes de ejecutar
CREATE INDEX index_name ON mytable(column);
tienes que correr
SELECT COUNT(1) IndexIsThere FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema=DATABASE() AND table_name='mytable' AND index_name='index_name';
Si IndexIsThere es 0, puede crear en el índice. Quizás pueda escribir un procedimiento almacenado para crear un índice en la tabla de su elección.
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 ;
Aquí hay una ejecución de muestra (Oye, ¿recuerdas esta tabla? Es de la pregunta que hiciste el 27 de junio de 2012):
mysql> show create table pixelsG
*************************** 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 pixelsG
*************************** 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>
Darle una oportunidad !!!
Tengo algo similar con el uso SELECT IF()
declaración en MySQL si está tratando de no tener procedimientos:
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;
Aquí el select if
tiene este formato if (condition, true_case, false_case)
. los select 'index index_1 exists'
es un caso ficticio. y _____
desempeña el papel de nombre de alias. Si no se hace el alias, se muestra el nombre de la columna y la fila. index index_1 exists
, que confunden aún más. para ser mas descriptivo puedes usar 'select ''index index_1 exists'' as _______;'
.
Si nombra el índice, la consulta fallará si el índice ya existe (probado en MySQL 8.0):
ALTER TABLE `my_table` ADD INDEX `col_idx` (`col` DESC);
Código de error: 1061. Duplicado key nombre ‘col_idx’;
Entonces, puede capturar la excepción e ignorarla, por ejemplo en 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
Más adelante puedes encontrar las anotaciones de otros programadores, tú igualmente eres capaz mostrar el tuyo si dominas el tema.