准备好的MySQLi中的通配符返回错误值

时间:2016-05-09 13:40:40

标签: php mysql

请参阅此帖子的底部以获取最新信息和当前状态

根据以下帖子提供的建议: Using wildcards in prepared statement - MySQLi

我设置了我的声明,它没有错误。但它没有返回正确的数据。

我的select语句为WHERE提供了这个:

 WHERE `Name` LIKE ?  order by `Name`

我的字符串设置绑定,然后是实际绑定。

$whatToBind = '%'. $whatName .'%';

$stmt = $mysqli->prepare($selectStr);
$stmt->bind_param('s', $whatToBind);
$stmt->execute();

当我得到回报时,它将完全错过它应该匹配的记录。 就像,如果我发送“Ken L”,我会收回“Ken Linton”的记录,而不是“Ken Lawton”。如果我输入“劳顿”,我根本就没有回报。

这是全面的典型行为。如果我搜索电话号码字段,则返回“658”,但“609-658”不返回。

如果有人能让我了解我所缺少的东西,那就太棒了。

示例返回显示我所指的确切示例:

未完成: enter image description here

空,但不应该是: enter image description here

返回all,包括应该与其他2一起存在的记录: enter image description here

要回答的问题: 还有一些事情需要检查:

  

检查MySQL / PHP交互字符集是否设置正确,通常使用:$ mysqli-> set_charset(“utf8mb4”);建立数据库连接后立即。

设置为utf8。虽然在设置之前它的行为相同。

  

你能显示$ mysqli->错误的输出吗?

没有错误。只是不完整的回报

  

你能告诉我们你的整个SQL查询吗?

它包含在屏幕抓取中。虽然,这只是一个简单的字符串。并且它没有说明准备好的陈述是什么样的。

  

您能否显示名称列的排序/ MySQL结构?

根据GoDaddy的phpMyAdmin

,这一切都是utf8
  

你可以在绑定之前显示$ whatName的值是什么吗?

它位于屏幕抓取的顶部。在其他任何事情发生之前,它会回复显示它。

此时我认为问题在于当我搜索的字段有空格或其他不是字母的字符时会发生什么。不是我准确传递的东西。但更像是,一旦准备好陈述,准备的东西就不匹配它所搜索的领域。当您在空间存在之前搜索字段时,不会发生这种情况。这就是为什么“肯”在100%的时间里工作,但“劳顿”完全失败。它是在空间之后。

我尝试了各种方式转换编码类型。我已经尝试了连接字符串的各种方法。我得到的结果要么没有好转,要么完全破坏它。

还有21个小时的奖励,如果有人有更多的想法。 在这一点上,我会更乐意为每个提供最佳信息的两个人提供25个奖励。似乎不公平地奖励一个而不是另一个。

2 个答案:

答案 0 :(得分:4)

$whatName可能是某种混合编码问题。

检查您的$whatName变量编码是否为UTF8。

mb_detect_encoding($whatName, 'UTF-8', true) // should return true

如果没有,那么您必须在mb_detect_encoding上使用mb_convert_encoding$whatName将其转换为utf8。

如果你还没有这样做

设置正确的字符集

$mysqli->set_charset('utf8mb4'); 
// if your MySQL version is lower than 5.5.3 then
// use $mysqli->set_charset('utf8'); 
在准备好的陈述之前

$stmt = $mysqli->prepare($selectStr);
$stmt->bind_param('s', $whatToBind);
$stmt->execute(); 

答案 1 :(得分:4)

  

请注意,此答案的详细信息不太可能自行解决问题。通过我自己的进一步测试,我确定在绑定之前将%_通配符附加到字符串不会影响它们绑定到查询的方式。

您目前要做的是将数据($whatName)与其每一侧的SQL指令%连接起来,而Prepared Statement解析器根本没有这个,因为它击败了准备声明的安全目的。

因此,解决方案是您只需要在插入时手动将变量连接到LIKE语句,而不是之前,就像您现在所做的那样。

以下示例将按您的意图执行:

$selectStr = WHERE `Name` LIKE CONCAT('%',?,'%') ORDER BY `Name`
$whatToBind = $whatName;
$stmt = $mysqli->prepare($selectStr);
$stmt->bind_param('s', $whatToBind);
$stmt->execute();

请注意dataquery 从不混合,直到执行准备好的语句。

关于MySQL的UTF-8和字符集的说明:

不要使用 utf8_ MySQL字符集,因为它们是真正的UTF-8的不完整子集,因此仍然会引发字符识别的严重问题。相反,您希望使用utf8mb4_字符集/排序/等。

字符编码可能是您问题的相关问题,我强烈建议您阅读this Stack Overflow Question上提供的优秀答案以及使用PHP mb_ multibyte string functions

还有一些事情需要检查:

  • 检查MySQL / PHP 交互字符集是否设置正确,通常在建立数据库连接后使用:$mysqli->set_charset("utf8mb4");

  • 您能否显示$mysqli->error的任何输出?

  • 您能告诉我们您的整个 SQL查询吗?

  • 您能否显示Names列的整理/ MySQL结构?

  • 您能否在绑定前显示$whatName的价值是什么? (虽然你的问题是有道理的,但是具有特定情况和特定结果以及预期结果的具体示例对我们调试非常有用。

  • 愚蠢但确保您的结果没有LIMIT! :-D