MySQL 5.7/8 环境下phpMyAdmin报#1191错误:已配置FULLTEXT索引但无法匹配列列表的技术问询
问题原因与解决办法
核心原因
你的问题出在FULLTEXT索引的匹配规则上:MySQL要求MATCH()子句中指定的列必须与某个已创建的FULLTEXT索引的列集合完全一致(不能是索引列的子集)。
看你的specimen表结构,现有的fulltext索引包含6个列:
FULLTEXT KEY `fulltext` (`topography_index`,`snop_code`,`clinical_history`,`macroscopic`,`microscopic`,`conclusion`)
但你的查询中MATCH()只用到了其中4个列:
MATCH (specimen.clinical_history,specimen.macroscopic,specimen.microscopic,specimen.conclusion)
MySQL找不到正好匹配这4个列的FULLTEXT索引,所以抛出#1191 - Can't find FULLTEXT index matching the column list错误。
至于为什么用*作为搜索词时能正常运行,大概率是MySQL 5.7的优化器存在宽松处理(或者说兼容bug),允许这种子集匹配;而MySQL 8.0严格执行了索引匹配规则,在线SQL fiddle环境也遵循了标准规则,所以报错。
解决办法
你有两种可行的修复方案:
方案1:修改查询语句,匹配现有索引的所有列
把MATCH()子句补充完整,包含现有fulltext索引的全部6个列:
WHERE MATCH (specimen.topography_index, specimen.snop_code, specimen.clinical_history,specimen.macroscopic,specimen.microscopic,specimen.conclusion) AGAINST ('$q' IN NATURAL LANGUAGE MODE)
这样就能直接复用已有的索引,不需要修改表结构。
方案2:创建新的FULLTEXT索引,仅包含查询用到的4个列
执行以下SQL语句,为查询中用到的4个列单独创建FULLTEXT索引:
ALTER TABLE specimen ADD FULLTEXT KEY ft_4cols (clinical_history, macroscopic, microscopic, conclusion);
创建完成后,原查询就能正常使用这个新索引,不需要修改查询语句。
额外提醒:SQL注入风险
你的PHP代码中直接将$_POST['query']拼接到SQL语句中,这存在严重的SQL注入漏洞,可能导致数据库被攻击或数据泄露。建议立即改用**预处理语句(Prepared Statements)**来执行查询,示例代码如下:
$q = $_POST['query']; $query = "SELECT * FROM specimen JOIN topography_index ON substring(specimen.topography_index, 2, 2) = topography_index.topography_index_code JOIN morphology ON morphology.morphology_code = specimen.snop_code LEFT JOIN specimen_image_lookup ON specimen_image_lookup.specimen_fk = specimen.specimen_pk LEFT JOIN image ON image.image_pk = specimen_image_lookup.image_fk LEFT JOIN specimen_audio_lookup ON specimen_audio_lookup.specimen_fk = specimen.specimen_pk LEFT JOIN audio ON audio.audio_pk = specimen_audio_lookup.audio_fk WHERE MATCH (specimen.clinical_history,specimen.macroscopic,specimen.microscopic,specimen.conclusion) AGAINST (? IN NATURAL LANGUAGE MODE) GROUP BY specimen.specimen_pk ORDER BY (specimen.room = 'f') DESC"; $stmt = mysqli_prepare($connection, $query); mysqli_stmt_bind_param($stmt, "s", $q); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt);
内容的提问来源于stack exchange,提问作者IlludiumPu36
相关产品推荐
相关产品推荐

