谁能告诉我为什么这个 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/