7

不知道我该怎么做。基本上,我有使用组合框填充的变量,然后通过 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);

谢谢你的帮助。C

4

7 回答 7

17

采用

$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);
于 2012-09-09T13:52:04.030 回答
5

其他几个答案提到了 SQL 注入的风险,还有几个明确提到使用准备好的语句,但没有一个明确显示你可以如何做到这一点,这对初学者来说可能是一个很大的要求。

我目前解决此问题的首选方法使用 MySQL“IF”语句来检查有问题的参数是否为 null/empty/0(取决于类型)。如果它是空的,那么它将字段值与自身进行比较(WHERE field1=field1总是返回true)。如果参数不为空/null/零,则将字段值与参数进行比较。

所以这里有一个使用 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在查询中引用多次,而只需绑定一次。

于 2019-08-23T18:12:52.000 回答
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);

注意 mysql_* 的 sql 注入和弃用,请改用 mysqli 或 PDO

于 2012-09-09T13:49:07.883 回答
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在生成查询之前转义。

于 2012-09-09T13:49:37.633 回答
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) );

大优势:即使子句数组完全为空,查询语法也是有效的。

于 2012-09-09T13:53:00.207 回答
0

首先,请阅读SQL 注入。其次,$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.
于 2012-09-09T13:53:33.287 回答
0

我想到了另外两种方法来解决这个问题:

SELECT * FROM moth_sightings
WHERE
      user_id = '$username'
      AND location = '%$value1%'

      AND english_name = $value2 ";

这将仅返回user_id位置字段包含的 this 的结果$value1如果 $value1 为空,这仍将返回 this 的所有行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位置或具有空白值的行。

于 2012-10-07T19:14:40.767 回答