php - WHERE 中使用多个 OR 术语的查询返回整个表

标签 php mysql sql pdo

谁能告诉我为什么这个 SQL 命令不起作用? 我有一个包含多个输入的表单,即 (id)=> 帐号,然后是名字、姓氏和电子邮件。我想让用户按照他们想要的方式进行搜索。

如果我将代码保留为“与”的方式..当仅搜索(id)时,它只会显示ID行,但如果我尝试这样做,它不会显示其余的搜索输入第一个、最后一个或电子邮件,但如果我将其更改为“OR”,则所有其他输入框都将显示单个结果,但如果我仅输入 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 '%%',因为这将匹配所有内容。您需要构建查询以仅使用表单提供的非空值。

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

最好先检查发布数据并取出非空值,然后放入数组中:

$searchFields = [];

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

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

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%' 相同。

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

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

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

$stmt->execute();

如上所述,我没有创建代码来以不同的方式处理 id 字段,但您应该能够处理它。如果您有许多不同类型的字段,您可能需要更改 $searchFields 的结构以包含类型信息。如果 id 是唯一的异常(exception),那么最简单的方法可能是在每个循环中使用 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 和名称不匹配,他们根本不会返回任何结果。

关于php - WHERE 中使用多个 OR 术语的查询返回整个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55821258/

相关文章:

php - 未定义索引 - 安全风险与性能与代码膨胀

mysql - InnoDB JPA,继续强制MyISAM

sql - 对象名称无效 'Table_2'

php - 如何在 PHP 中获取文件的扩展名?

php - 如何检查在 ON DUPLICATE 语句中更新和插入了多少行?

php - 使用 Eloquent 更新 MYSQL 中的产品数量

MySQL 复杂查询 - 使用 UNION ALL 和内部 JOIN 对多个数据库求和

php - html 多个输入字段

java - 如何在Java插入准备语句中用空字符串替换Null

sql - 在 Postgresql 中按窗口函数结果过滤