MySQL: Tạo chỉ mục Nếu không tồn tại


62

Có cách nào để tạo một chỉ mục trong MySQL nếu nó không tồn tại?

MySQL không hỗ trợ định dạng rõ ràng:

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

Phiên bản MySQL ( mysql -V) là 5.1.48, nhưng tôi nghĩ rằng MySQL thiếu CREATE INDEX IF NOT EXISTkhả năng trong tất cả các phiên bản của nó.

Cách đúng đắn để tạo chỉ mục chỉ khi nó chưa tồn tại trong MySQL?

Câu trả lời:


36

Chức năng đó không tồn tại. Có hai điều cần lưu ý:

Tạo chỉ mục bằng mọi cách

Bạn có thể tạo chỉ mục theo cách mà chỉ mục được tạo mà không cần kiểm tra chỉ mục đó tồn tại trước thời hạn. Ví dụ: bạn có thể chạy như sau:

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

Điều này chắc chắn sẽ tạo ra hai chỉ mục mà không cần kiểm tra. Mỗi chỉ mục sẽ được gán một tên (có lẽ là cột_to_index, cột_to_index_1). Tất nhiên, bạn đang cố gắng tránh điều đó.

Trước tiên hãy kiểm tra THÔNG TIN_SCHema

Dưới đây là cách bố trí của 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>

Bạn chỉ có thể truy vấn sự tồn tại của chỉ mục theo tên. Ví dụ: trước khi bạn chạy

CREATE INDEX index_name ON mytable(column);

Bạn cần phải chạy

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

Nếu IndexIsThere là 0, bạn có thể tạo trong chỉ mục. Có lẽ bạn có thể viết một thủ tục được lưu trữ để tạo một chỉ mục trên bảng bạn chọ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 ;

Đây là một lần chạy mẫu (Hey Ghi bảng này? Đó là từ câu hỏi bạn đã hỏi lại vào ngày 27 tháng 6 năm 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>

Hãy thử một lần !!!


37

Tôi có một cái gì đó tương tự với việc sử dụng SELECT IF()câu lệnh trong MySQL nếu bạn đang cố gắng không có các thủ tục:

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;

Ở đây select ifcó định dạng này if (condition, true_case, false_case). Đây select 'index index_1 exists'là một trường hợp giả. và _____đóng vai trò của tên bí danh. Nếu bí danh không được thực hiện thì cả tên cột và hàng đều hiển thị index index_1 exists, điều này gây nhầm lẫn hơn nữa. để được mô tả nhiều hơn bạn có thể sử dụng 'select ''index index_1 exists'' as _______;'.


3

Nếu bạn đặt tên cho chỉ mục, truy vấn sẽ thất bại nếu chỉ mục đã tồn tại (được thử nghiệm trong MySQL 8.0):

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

Mã lỗi: 1061. Tên khóa trùng lặp 'col_idx';

Vì vậy, bạn chỉ có thể bắt ngoại lệ và bỏ qua nó, ví dụ như trong 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
    }
}

2
SELECT COUNT(*)
FROM information_schema.statistics
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'table_name' 
  AND INDEX_NAME = 'index_name'; 

Truy vấn của tôi sẽ cung cấp cho bạn số lượng chỉ mục hiện diện trên một bảng với một tên_bảng cụ thể. Dựa trên số đó, bạn có thể quyết định có ban hành CREATE INDEXlệnh hay không.

Đã thử nghiệm trên phiên bản MySQL 5.5 .

MariaDB hỗ trợ IF NOT EXISTScú pháp . Bạn có thể sử dụng CREATE INDEX IF NOT EXISTSở đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.