不确定我该怎么做。基本上我有变量用组合框填充,然后传递以通过where子句形成MQSQL查询的过滤器。我需要做的是允许用户将组合框留空,然后在where子句中忽略该变量。这可能吗?
即,来自此代码。假设填充$ value1的组合框保留为空,是否有任何方法可以忽略它并仅应用第二个过滤器。
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND location = '$value1' AND english_name = $value2 ";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
感谢您的帮助。 ç
答案 0 :(得分:12)
使用
$where = "WHERE user_id = '$username'";
if(!empty($value1)){
$where .= "and location = '$value1'";
}
if(!empty($value2 )){
$where .= "and english_name= '$value2 '";
}
$query = "SELECT * FROM moth_sightings $where";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
答案 1 :(得分:1)
其他几个答案都提到了SQL注入的风险,还有几个答案明确地提到了使用预准备语句,但是没有一个明确说明如何执行,这对于初学者可能是一个很大的要求。
我当前解决此问题的首选方法是使用MySQL“ IF”语句检查所涉及的参数是否为null / empty / 0(取决于类型)。如果为空,则将字段值与其自身进行比较(WHERE field1=field1
始终返回true
)。如果参数不为空/空/零,则将字段值与参数进行比较。
因此,这是一个使用MySQLi预准备语句的示例(假设$ mysqli是已实例化的mysqli对象):
$sql = "SELECT *
FROM moth_sightings
WHERE user_id = ?
AND location = IF(? = '', location, ?)
AND english_name = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('ssss', $username, $value1, $value1, $value2);
$stmt->execute();
(我假设$value2
是基于字段名称的字符串,尽管OP的示例SQL中没有引号。)
MySQLi中无法将同一参数绑定到语句中的多个占位符,因此我们必须显式绑定$value1
两次。在这种情况下,MySQLi的优点是显式键入参数-如果我们将$value1
作为字符串传递,我们知道我们需要将其与空字符串''
进行比较。如果$value1
是整数值,我们可以像这样明确声明:
$stmt->bind_param('siis', $username, $value1, $value1, $value2);
,然后将其与0
进行比较。
这是一个使用命名参数的PDO示例,因为我认为它们会导致更少的计数而使代码更具可读性:
$sql = "SELECT *
FROM moth_sightings
WHERE user_id = :user_id
AND location = IF(:location_id = '', location, :location_id)
AND english_name = :name";
$stmt = $pdo->prepare($sql);
$params = [
':user_id' => $username,
':location_id' => $value1,
':name' => $value2
];
$stmt->execute($params);
请注意,使用PDO命名参数,我们可以在查询中多次引用:location_id
,而只需绑定一次即可。
答案 2 :(得分:0)
当然,
$sql = "";
if(!empty($value1))
$sql = "AND location = '{$value1}' ";
if(!empty($value2))
$sql .= "AND english_name = '{$value2}'";
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' {$sql} ";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
注意sql注入和弃用mysql_ *,改用mysqli或PDO
答案 3 :(得分:0)
if ( isset($value1) )
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND location = '$value1' AND english_name = $value2 ";
else
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND english_name = $value2 ";
但是,您还可以创建一个函数来根据您的输入返回查询。
并且在生成查询之前也不要忘记逃避$values
。
答案 4 :(得分:0)
1。)不要使用简单的mysql php扩展,使用高级mysqli扩展或更安全的PDO / MDB2包装。
2。)不要像那样指定完整的语句(除了你甚至不编码和转义给定的值...)。而是使用这样的东西:
sprintf("SELECT * FROM moth_sightings WHERE 1=1 AND %s", ...);
然后使用包含实际从表单中获取的所有值的数组填充该原始查询:
$clause=array(
'user_id="'.$username.'"',
'location="'.$value1.'"',
'english_name="'.$value2.'"'
);
您可以以任何方式操纵此数组,例如测试空值或其他任何方式。现在只是破坏数组来完成上面的原始问题:
sprintf("SELECT * FROM moth_sightings WHERE 1=1 AND %s",
implode(' AND ', $clause) );
大优势:即使子句数组完全为空,查询语法也是有效的。
答案 5 :(得分:0)
首先,请阅读SQL Injections。 其次,$ r = mysql_numrows($ result)应为$ r = mysql_num_rows($ result);
您可以在MySQL中使用IF,如下所示:
SELECT * FROM moth_sightings WHERE user_id = '$username' AND IF('$value1'!='',location = '$value1',1) AND IF('$value2'!='',english_name = '$value2',1); -- BUT PLEASE READ ABOUT SQL Injections. Your code is not safe.
答案 6 :(得分:0)
我想到了另外两种方法来解决这个问题:
SELECT * FROM moth_sightings
WHERE
user_id = '$username'
AND location = '%$value1%'
AND english_name = $value2 ";
这将仅返回此user_id
的结果,其中位置字段包含$value1
。 如果$ value1为空,这仍将返回此user_id
的所有行,空白或不空白。
SELECT * FROM moth_sightings
WHERE
user_id = '$username'
AND (location = '$value1' OR location IS NULL OR location = '')
AND english_name = $value2 ";
这将为您提供此user_id
的所有行,其$value1
位置或空值。