【问题标题】:Query with multiple OR terms in WHERE returns the whole table在 WHERE 中使用多个 OR 项的查询返回整个表
【发布时间】:2019-04-24 01:47:58
【问题描述】:

谁能告诉我为什么这个 SQL 命令不起作用? 我有一个包含多个输入的表单,即 (id)=> 帐号,然后是名字、姓氏和电子邮件。我想允许用户随意搜索。

如果我以“与 AND”的方式保留代码 .. 仅搜索 (id) 时,它只会显示 ID 行,但如果我尝试,它不会显示其余搜索输入第一个,最后一个或电子邮件,但如果我将其更改为“或”,那么所有其他输入框都将显示单个结果,但如果我只输入 id“帐号”,我将在我的表格中显示每个客户.. 为什么? 我错过了什么,所以我的代码可以搜索所有输入? 谢谢

$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$firstname = "%$firstname%";
$lastname = "%$lastname%";
$email = "%$email%";    
$id = $_POST['id']; 



    $stmt = $conn->prepare("
    SELECT * FROM `Demo_Guests`
    WHERE  
    firstname LIKE :firstname 
    AND lastname LIKE :lastname
    AND email LIKE :email AND id = :id

    ");
    $stmt->bindValue(':id', $id, PDO::PARAM_INT);
    $stmt->bindValue(':firstname', $firstname,PDO::PARAM_STR);
    $stmt->bindValue(':lastname', $lastname,PDO::PARAM_STR);
    $stmt->bindValue(':email', $email,PDO::PARAM_STR);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_OBJ);

foreach($result as $row){
            echo "<tr><td> 
            <a href=\"main_table.php?id={$row->id}\"> " . $row->id . "</a><br></td>";
            echo "<td>" . $row->firstname . "</td>";
            echo "<td>" . $row->lastname . "</td>";
            echo "<td>" . $row->email . "</td>";
            echo "<td>" . $row->reg_date . "</td></tr>";


}

【问题讨论】:

  • 当你使用 OR 语句时,你需要确保你没有firstname LIKE '%%',因为它会匹配所有的东西。您需要构建查询以仅使用表单提供的非空值。
  • @Jerry 你在那里写的一段相当不错的代码。我刚看到。今晚我会尝试一下,看看我是否能完成我想要的……绝对是一种不同的方法,但我可以看到它是如何完全起作用的。现在我只是在学习基础知识.. 我今晚会再发一张纸条,告诉你我是否能成功!谢谢
  • @Jerry 一个简单的问题.. 为什么当我使用 AND 时,一切正常,但是当我将 id 添加到整个 sql 命令时,它会禁用它,它只适用于 id?
  • 当您使用 AND 时,您只会得到符合所有条件的结果。因此,当您与 id 进行 AND 时,可能只有一条记录可以匹配。
  • @Jerry 很好。我将处理你今晚帮助我编写的代码,看看我是怎么做的。谢谢..如果有任何进一步的帮助,我可以更新你吗?可以吗?

标签: php mysql sql pdo


【解决方案1】:

扩展我上面的评论,这是:

当您使用 OR 语句时,您需要确保您没有 firstname LIKE '%%',因为这将匹配所有内容。您需要构建查询以仅使用表单提供的非空值。

这意味着您必须从搜索表单中的非空输入构建查询,并省略与表中所有内容匹配的术语。

最好先检查帖子数据并取出非空值放入数组中:

$searchFields = [];

foreach (['id', 'firstname', 'lastname', 'email'] as $searchField) {
    if (!empty($_POST[$searchField])) {
        $searchFields[$searchField] = $_POST[$searchField];
    }
}

这将为您提供用户实际填写的所有字段的列表。您将需要该列表两次 - 一次用于构建查询,一次用于绑定。

if (count($searchFields) > 0) {

    $queryStr = "SELECT * FROM `Demo_Guests` WHERE 0";

    foreach (array_keys($searchFields) as $fieldName) {
        $queryStr .= " OR " . $fieldName . " LIKE :" . $fieldName;
    }

    // ... the rest of the code goes here

} else {
    return "you gotta give me something to work with!";
}

两个注意事项:1)我没有将 id 设为特殊情况,您需要在代码中这样做。 2) WHERE 0 是一个懒人的捷径,你以后不需要做任何额外的逻辑来决定是否需要在第一个任期内添加OR。变成WHERE 0 OR firstname LIKE '%Alice%',功能和WHERE firstname LIKE '%Alice%'一样。

构建查询字符串后,您可以按照上面的方式准备它,然后使用您用于构建查询的相同数组执行绑定。

$stmt = $conn->prepare($queryStr);

foreach($searchFields as $fieldName => $fieldValue) {
    $stmt->bindValue(':'.$fieldName, "%$fieldValue%", PDO::PARAM_STR);
}

$stmt->execute();

如上所述,我没有创建代码来区别对待 id 字段,但你应该能够处理它。如果您有很多不同类型的字段,您可能希望更改 $searchFields 的结构以包含类型信息。如果 id 是唯一的例外,那么在每个循环中使用 if 语句可能是最简单的。

添加:

此搜索将返回数据库中与任何输入条件匹配的所有记录。因此,如果用户搜索 firstName LIKE '%Ali%' OR lastName LIKE '%Smi%',您可能会返回 Alice Smith、Alicia Smith、Fred Smith 和 Alice Jones。

但是,如果您只希望该搜索返回 Alice Smith 和 Alicia Smith,而不是使用 OR,则使用 AND。搜索将产生更少的结果,因此对输入错误的名称等的宽容度会有所降低。

对代码的唯一其他修改是懒人快捷方式也必须更改:

if (count($searchFields) > 0) {

    $queryStr = "SELECT * FROM `Demo_Guests` WHERE 1";

    foreach (array_keys($searchFields) as $fieldName) {
        $queryStr .= " AND " . $fieldName . " LIKE :" . $fieldName;
    }

    // ... the rest of the code goes here

} else {
    return "you gotta give me something to work with!";
}

WHERE 1 AND first_name LIKE '%Ali%' 在功能上与WHERE first_name LIKE '%Ali%' 相同。

请注意,在这种情况下,如果用户指定了 ID,您将希望完全忽略其他搜索字段。否则,如果他们指定的 id 和 name 不匹配,他们根本不会得到任何结果。

【讨论】:

  • 代码就像一个魅力......它完全改变了我过去查询的方式......我以前没有见过这种方法......我现在知道如何在未来构建它。 . 我确实删除了 OR 并将其保留为 " $queryStr .= $fieldName . " LIKE :" . $fieldName;"然后绑定值,我简单地将其写为“ $stmt->bindValue(':'. $fieldName, "%$fieldValue%", PDO::PARAM_STR); ”,因此它可以搜索任何匹配的内容。它知道地址的一部分会很不方便,也许不是全部,但不会找到记录,因为它不是完全匹配的..无论如何,我学到了很多!
  • 是的,添加通配符% 字符是对的。我本来打算把它们放进去。至于省略OR,如果这个人在搜索表单中填写了多个字段,你最终会遇到麻烦。
  • 哇。我刚试过..它抛出了一个错误.. SQLSTATE[HY093]: Invalid parameter number: parameter was not defined.. 我没想到.. 无论如何.. 刚刚添加它,一切都很好.. 你是一个总亲..希望我亲自认识你向你学习
  • 乐于助人!如果您将此答案标记为正确,它将帮助其他有相同问题的人找到此答案。
  • 我很久以前就试过了,但我明白了.. 感谢您的反馈!声望低于15的人的投票会被记录,但不要改变公开显示的帖子分数……你有什么渠道或方式关注你吗?我真的需要非常擅长这个
猜你喜欢
  • 2012-10-28
  • 1970-01-01
  • 2014-05-30
  • 2020-10-26
  • 2020-10-05
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多