当LIKE条件包含多个非通配符时,prepare查询无法返回结果

时间:2019-07-02 21:21:10

标签: mysql prepared-statement sql-like

我正在尝试使用准备好的语句搜索用户表。当搜索字符串包含多个字符或看似随机的字符时,不会返回任何结果(即onn失败,但n成功)。数据库中的数据应在我使用的测试查询中至少返回一个结果,但不返回任何结果。我不确定这与字符长度有关,但是我尝试过的每个搜索查询中有多个字符以上的查询都会在至少应有一个结果的情况下无法返回结果。

我尝试了很多形式的查询,但都没有碰到运气。我已经调整了表格和字段的排序规则,以增加区分大小写的能力。我搜索了类似的帖子,但找不到。我也阅读了MySQL preparelike文档。最初,我开始使用PHP PDO连接进行更复杂的查询,但将其范围缩小到一个简单的SELECT并将其隔离到MySQL准备中。


*所有这些查询都是在MySQL Workbench中执行的

PREPARE stm FROM "SELECT firstName, lastName, displayName FROM `users` WHERE ? LIKE CONCAT('%',?,'%') ORDER BY ? asc";
SET @searchCol = 'firstName';
set @searchQuery = 'o';
set @orderBy = 'lastName';
EXECUTE stm USING @searchCol, @searchQuery, @orderBy;
deallocate prepare stm;

预期: Trevor,Bloom,Trev Bloom
已收到:没有任何操作
*我偶然发现了这个案子。我不确定为什么单个n会起作用,而单个o不会起作用。


PREPARE stm FROM "SELECT firstName, lastName, displayName FROM `users` WHERE ? LIKE CONCAT('%',?,'%') ORDER BY ? asc";
SET @searchCol = 'firstName';
set @searchQuery = 'nn';
set @orderBy = 'lastName';
EXECUTE stm USING @searchCol, @searchQuery, @orderBy;
deallocate prepare stm;

期望:安娜,霍根,安娜·霍根
已收到:没有


PREPARE stm FROM "SELECT firstName, lastName, displayName FROM `users` WHERE ? LIKE CONCAT('%',?,'%') ORDER BY ? asc";
SET @searchCol = 'firstName';
set @searchQuery = 'n';
set @orderBy = 'lastName';
EXECUTE stm USING @searchCol, @searchQuery, @orderBy;
deallocate prepare stm;

预期:与%n%相匹配的多个结果
已收到:预期结果


我还尝试了删除CONCAT('%',?,'%'),将其替换为?,并将@searchQuery更改为%<query>%的情况,但是结果与上面相同。

据我所知,不会生成任何错误消息或异常日志。

utf8表以及适用的列的字符集/排序规则分别设置为utf_general_ciusers

下面是SHOW VARIABLES LIKE "%version%"

的结果

'innodb_version','5.7.26'
'protocol_version','10'
'slave_type_conversions',''
'tls_version','TLSv1,TLSv1.1'
'version','5.7.26-0ubuntu0.16.04.1-log'
'version_comment','(Ubuntu)'
'version_compile_machine','x86_64'
'version_compile_os','Linux'

1 个答案:

答案 0 :(得分:1)

列名不能使用?占位符。占位符用于代替值,它们被执行语句时提供的文字值替换。

写作时

PREPARE stm FROM "SELECT firstName, lastName, displayName FROM `users` WHERE ? LIKE CONCAT('%',?,'%') ORDER BY ? asc";
SET @searchCol = 'firstName';
set @searchQuery = 'o';
set @orderBy = 'lastName';
EXECUTE stm USING @searchCol, @searchQuery, @orderBy;

它执行的查询是:

SELECT firstName, lastName, displayName 
FROM `users` 
WHERE 'firstName' LIKE CONCAT('%','o','%') 
ORDER BY 'lastName' asc

它不是在测试firstName列,而是以文字字符串对其进行测试,这永远是不正确的,因为o中没有firstName。而且也不是按列排序;它是按常数排序的,这意味着任何顺序。

您需要使用普通串联来代替列名,而不是占位符。

SET @searchCol = 'firstName';
set @searchQuery = 'o';
set @orderBy = 'lastName';
PREPARE stm FROM CONCAT("
    SELECT firstName, lastName, displayName 
    FROM `users` 
    WHERE ", @searchCol, " LIKE CONCAT('%',?,'%') 
    ORDER BY ", @orderBy, " asc");
EXECUTE stm USING @searchQuery;