Определение существования индекса таблицы MySQL перед созданием - PullRequest
9 голосов
/ 02 сентября 2010

Процесс автоматической миграции базы данных нашей системы включает запуск сценариев .sql, содержащих новые определения таблиц и сопровождающие их индексы.

Мне требуется возможность создавать эти таблицы и индексы, только если они еще не существуют.О таблицах заботятся, используя IF NOT EXISTS, но при создании индексов такой синтаксис не существует.

Я пытался написать хранимую процедуру, показанную ниже, но, по-видимому, это не удается, поскольку вы не можете выбрать изпоказать заявление.

DELIMITER $$
DROP PROCEDURE IF EXISTS csi_add_index $$
CREATE PROCEDURE csi_add_index(in theTable varchar(128), in theIndexName varchar(128), in theIndexColumns varchar(128)  )
BEGIN
 IF(((SELECT COUNT(*) FROM (SHOW KEYS FROM theTable WHERE key_name = theIndexName)) tableInfo = 0) THEN
   SET @s = CONCAT('CREATE INDEX ' , theIndexName , ' ON ' , theTable, '(', theIndexColumns, ')');
   PREPARE stmt FROM @s;
   EXECUTE stmt;
 END IF;
END $$

Я подумал об отбрасывании и воссоздании, но этот процесс, как он существует, предполагает, что он не встретит ошибок, поэтому я сначала хочу проверить существование.

Есть ли другой способ получить индексы таблицы, чтобы проверить, существует ли индекс до его создания, или кто-нибудь может предложить лучший подход к управлению этим?

РЕДАКТИРОВАТЬ: Обратите внимание, что этоавтоматизированная процедура, без вмешательства человека.

Ответы [ 7 ]

12 голосов
/ 02 сентября 2010
SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE
`TABLE_CATALOG` = 'def' AND `TABLE_SCHEMA` = DATABASE() AND
`TABLE_NAME` = theTable AND `INDEX_NAME` = theIndexName
8 голосов
/ 02 сентября 2010

После еще одного удара головой о стену и интенсивного поиска в Интернете я нашел таблицу information_schema.statistics . Содержит имя индекса для таблицы.

Моя хранимая процедура теперь

DELIMITER $$

DROP PROCEDURE IF EXISTS csi_add_index $$
CREATE PROCEDURE csi_add_index(in theTable varchar(128), in theIndexName varchar(128), in theIndexColumns 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('CREATE INDEX ' , theIndexName , ' ON ' , theTable, '(', theIndexColumns, ')');
   PREPARE stmt FROM @s;
   EXECUTE stmt;
 END IF;
END $$

и работает как положено.

Спасибо за предложения.

1 голос
/ 16 июля 2018

Поскольку для текста и больших двоичных объектов нужен размер, я добавил его в хранимую процедуру.

DROP PROCEDURE IF EXISTS createIndex;

DELIMITER $$
-- Create a temporary stored procedure for checking if Indexes exist before attempting to re-create them. => can be called
$$
CREATE PROCEDURE `createIndex`(
    IN `tableName` VARCHAR(128),
    IN `indexName` VARCHAR(128),
    IN `indexColumns` VARCHAR(128),
    IN `indexSize` VARCHAR(128)
)
BEGIN
  IF((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() AND table_name = tableName AND index_name = indexName)  = 0) THEN
        IF(indexSize > 0) THEN
            SET @sqlCommand = CONCAT('CREATE INDEX ' , indexName , ' ON ' , tableName, '(', indexColumns, '(' , indexSize, '))');
        ELSE
            SET @sqlCommand = CONCAT('CREATE INDEX ' , indexName , ' ON ' , tableName, '(', indexColumns, ')');
        END IF;
    PREPARE _preparedStatement FROM @sqlCommand;
    EXECUTE _preparedStatement;
  END IF;
END $$
DELIMITER ;
1 голос
/ 02 сентября 2010

Вы можете запросить базу данных infomration_schema для этой и многих других полезных сведений

http://dev.mysql.com/doc/refman/5.0/en/information-schema.html

1 голос
/ 02 сентября 2010

Используйте SHOW INDEX FROM mytable FROM mydb; и проверьте, присутствует ли индекс - каждая из возвращаемых строк представляет одну часть индекса; столбец, который, вероятно, больше всего вас заинтересовал бы, это Key_name, поскольку он содержит название индекса. Документация здесь .

0 голосов
/ 06 января 2012

Не новая версия, а более полное решение, которое включает вызов для создания 2 индексов.

USE MyDatabaseName;
DELIMITER $$
-- Create a temporary stored procedure for checking if Indexes exist before attempting to re-create them.
DROP PROCEDURE IF EXISTS `MyDatabaseName`.`spCreateIndex` $$
CREATE PROCEDURE `MyDatabaseName`.`spCreateIndex` (tableName VARCHAR(128), in indexName VARCHAR(128), in indexColumns VARCHAR(128))
BEGIN
  IF((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() AND table_name = tableName AND index_name = indexName)  = 0) THEN
    SET @sqlCommand = CONCAT('CREATE INDEX ' , indexName , ' ON ' , tableName, '(', indexColumns, ')');
    PREPARE _preparedStatement FROM @sqlCommand;
    EXECUTE _preparedStatement;
  END IF;
END $$
DELIMITER ;

-- Create the Indexes if they do not exist already.
CALL spCreateIndex('MyCustomers', 'idxCustNum', 'CustomerNumber');
CALL spCreateIndex('MyProducts', 'idxProductName', 'ProductName');

DELIMITER $$
-- Drop the temporary stored procedure.
DROP PROCEDURE IF EXISTS `MyDatabaseName`.`spCreateIndex` $$
DELIMITER ;
0 голосов
/ 02 сентября 2010

Вы можете просто создать другую таблицу с правильными индексами, скопировать все из старой таблицы, а затем отбросить ее и переименовать новую таблицу обратно в прежнюю.Немного хакерский и может быть немного тяжелым для больших столов, но все же довольно просто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...