与this question类似,我想要做的是确定索引是否存在,但是使用多个列。例如,我有一张酒店房间的下表:
CREATE TABLE `rooms` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`res_num` int(11) NOT NULL,
`room_id` int(11) NOT NULL,
`date` date NOT NULL,
`adults` tinyint(4) NOT NULL DEFAULT '0',
`children` tinyint(4) NOT NULL DEFAULT '0',
`young_children` tinyint(4) NOT NULL DEFAULT '0',
`pets` tinyint(4) NOT NULL DEFAULT '0',
`smoking` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `room_id` (`room_id`,`date`),
KEY `res_num` (`res_num`),
KEY `date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=97449 DEFAULT CHARSET=utf8
我想在room_id
和date
上添加单个索引,前提是它已经存在。执行SHOW INDEX
会产生以下输出:
mysql> show index from rooms;
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rooms | 0 | PRIMARY | 1 | id | A | 67399 | NULL | NULL | | BTREE | | |
| rooms | 0 | room_id | 1 | room_id | A | 58 | NULL | NULL | | BTREE | | |
| rooms | 0 | room_id | 2 | date | A | 67399 | NULL | NULL | | BTREE | | |
| rooms | 1 | res_num | 1 | res_num | A | 67399 | NULL | NULL | | BTREE | | |
| rooms | 1 | date | 1 | date | A | 6739 | NULL | NULL | | BTREE | | |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
9 rows in set (0.01 sec)
我还可以通过执行以下操作将输出限制为有问题的列:
SHOW INDEX FROM rooms WHERE Column_name = 'room_id' OR Column_name = 'date';
但是,各列可能有自己的索引,例如上面案例中的date
列。如何确定所有属于同一Key_name
的多个列上存在索引?
答案 0 :(得分:2)
首先,发出像
这样的命令SHOW INDEX FROM rooms
WHERE Seq_in_index > 1
AND Column_name IN ("id", "date")
您将获得基于多个列的索引列表,并且至少包含您需要的一个列。从结果列表中,您获取Key_name,然后对每个结果重复查询:
SHOW INDEX FROM rooms WHERE Key_name=?
如果结果中有两行,并且您需要的两列都在列表中,那么您的索引就存在。
如果有人知道如何在不依赖外部编程语言的情况下在纯SQL中执行此操作,或建议更优化的方法,请改进答案
答案 1 :(得分:2)
TimSparrow的回答确实指出了我在这里的正确方向,所以一定要提出他的答案。以下是如何在不依赖任何外部编程语言的情况下一步完成所有操作:
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'rooms'
AND index_name = (
SELECT index_name
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'rooms'
AND Seq_in_index = 2
AND Column_name IN ("room_id", "date")
)
AND Column_name IN ("room_id", "date")
只需将索引包含的所有列放在Column_name
部分中,然后将Seq_in_index
更改为索引中的列数。如果它返回与Seq_in_index
相同的值,则索引存在。
您还可以使用2列以上的内容轻松将其扩展到索引。例如,如果使用所有这些列存在索引,则以下内容将返回5
:
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'rooms'
AND index_name = (
SELECT index_name
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'rooms'
AND Seq_in_index = 5
AND Column_name IN ("room_id", "date", "foo", "bar", "baz")
)
AND Column_name IN ("room_id", "date", "foo", "bar", "baz")
答案 2 :(得分:1)
您可以检查使用以下语句索引的多个列,假设您不希望将多个列作为主键索引检查
select table_schema, table_name, index_name, group_concat(column_name) column_name
from information_schema.statistics
where table_schema = 'your_schema'
and index_name != 'PRIMARY'
group by table_schema, table_name, index_name
having count(column_name) > 1