我正在使用PHP预处理语句在我的网站上创建一个高级搜索页面,以使用布尔全文搜索来查询MySQL数据库MyISAM表。
它非常类似于Google提供的高级搜索的第一部分,其中包含以下标准:
我检索每个输入值,清理并处理字符串集合的每个部分,然后通过准备好的语句附加相应的信息以形成mySQL查询。
所以本质上是针对以下搜索:
将输出为此字符串:
seagate* toshiba*
查询会产生如下内容:
SELECT id, description
FROM `items`
WHERE MATCH (description)
AGAINST ('seagate* toshiba*' IN BOOLEAN MODE)
其中列出所有行,其中包含“seagate”后跟任何内容,“toshiba”后跟说明字段中的任何内容。
这很好,输出:
-(750gb*) -(320gb*) seagate* toshiba*
其中列出了上述所有行,但在说明字段中排除了“750gb”和“320gb”的所有行。
通过在“所有这些单词”字符串中添加一个值,我们得到一个输出:
+(16mb*) +(7200rpm*) -(750gb*) -(320gb*) seagate* toshiba*
这将列出上述所有行,但仅显示描述字段中包含“16mb”和“7200rpm”的下降。
现在有问题的部分。如果我要使用“Exact word of statement”字符串并添加值“serial ata 600”,我们将获得输出:
+(16mb*) +(7200rpm*) -(750gb*) -(320gb*) +("serial ata 600") seagate* toshiba*
使用phpmyadmin作为sql查询运行此字符串和结果查询我得到一个匹配搜索条件的2行结果集。
然而,当我在我的网站上运行时,我得到6行的结果,这表示+(“serial ata 600”)“被完全忽略。
如果我只输入字符串“Exact word of statement”的值,那么我们将得到一个输出:
+("serial ata 600")
结果将指示此字符串将列出包含“serial”或“ata”或“600”的所有行。
通过直接在mysql中运行相同的查询,此结果将列出包含“serial ata 600”字样的所有行。
在MySQL definition of this operator中声明:
A phrase that is enclosed within double quote (“"”) characters matches
only rows that contain the phrase literally, as it was typed.
在MySQL中就是这种情况,但是当使用PHP作为Prepared Statement运行相同的查询时,会返回不同的结果集。
以下是准备好的声明:
if ($result = $link->prepare("
SELECT id, description
FROM `items`
WHERE MATCH (description)
AGAINST (? IN BOOLEAN MODE)
"))
{
$result->bind_param("s", $pattern);
... ETC
}
以下是$pattern
之前的输出:
+("serial ata 600")
有没有人可能会提出这种行为的原因,因为我认为没有任何理由在PHP和MySQL之间的工作方式上有任何不同。
我可以提供任何有关如何根据请求生成字符串的其他代码,但输出与我的示例中的相同。
非常感谢任何建议/建议/意见/反馈或评论。
答案 0 :(得分:2)
这是一个准备好的陈述落在他们脸上的地方。在内部,准备引擎将做相当于:
$quoted = mysql_real_escape_string('+("serial ata 600")');
,它相当于
+(\"serial ata 600\")
现在你不再使用3个字的引用短语了,你发送的是以下单词:
+("serial
ata
600")
这是因为"
引号是SQL元字符,您需要将它们视为元字符。但是,由于它们是元字符,准备引擎会引用它们,将它们缩减为正常的简称引号,现在它们不再包含您的搜索短语。他们已经成为搜索短语的一部分。
不知道这是否真的有用,但你可能不得不重写准备好的陈述更像
... MATCH AGAINST (CONCAT('("', ?, '")'))