snippetsqlCritical
MySQL: Create index If not exists
Viewed 0 times
createmysqlexistsindexnot
Problem
Is there a way to create an index in MySQL if it does not exist?
MySQL does not support the obvious format:
MySQL version (
What's the right way to create an index only if it does not already exist in MySQL?
MySQL does not support the obvious format:
CREATE INDEX IF NOT EXISTS index_name ON table(column)
ERROR 1064 (42000): You have an error in your SQL syntax;...MySQL version (
mysql -V) is 5.1.48, but I think that MySQL lacks the CREATE INDEX IF NOT EXIST ability in all of its versions.What's the right way to create an index only if it does not already exist in MySQL?
Solution
That functionality does not exist. There are two things to keep in mind:
Create the Index Anyway
You can generate index in such a way that the index is created without checking if the index exists ahead of time. For example, you can run the following:
This will definitely create two indexes without checking. Each index will be assigned a name (perhaps column_to_index,column_to_index_1). Of course, you are trying to avoid that.
Check INFORMATION_SCHEMA first
Here is the layout of INFORMATION_SCHEMA.STATISTICS:
You could just query for the existence of the index by name. For example, before you run
You need to run
If IndexIsThere is 0, you can create in the index. Perhaps you can write a stored procedure to create an index on the table of your choice.
Here is a sample run (Hey Remember This Table? It's from the question you asked back on June 27, 2012) :
Give it a Try !!!
Create the Index Anyway
You can generate index in such a way that the index is created without checking if the index exists ahead of time. For example, you can run the following:
ALTER TABLE table_name ADD INDEX (column_to_index);
ALTER TABLE table_name ADD INDEX (column_to_index);This will definitely create two indexes without checking. Each index will be assigned a name (perhaps column_to_index,column_to_index_1). Of course, you are trying to avoid that.
Check INFORMATION_SCHEMA first
Here is the layout of 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>You could just query for the existence of the index by name. For example, before you run
CREATE INDEX index_name ON mytable(column);You need to run
SELECT COUNT(1) IndexIsThere FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema=DATABASE() AND table_name='mytable' AND index_name='index_name';If IndexIsThere is 0, you can create in the index. Perhaps you can write a stored procedure to create an index on the table of your choice.
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 ;Here is a sample run (Hey Remember This Table? It's from the question you asked back on June 27, 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>Give it a Try !!!
Code Snippets
ALTER TABLE table_name ADD INDEX (column_to_index);
ALTER TABLE table_name ADD INDEX (column_to_index);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>CREATE INDEX index_name ON mytable(column);SELECT COUNT(1) IndexIsThere FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema=DATABASE() AND table_name='mytable' AND index_name='index_name';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 ;Context
StackExchange Database Administrators Q#24531, answer score: 74
Revisions (0)
No revisions yet.