[英]Possible to have PHP MYSQL query ignore empty variable in WHERE clause?
不知道我怎么能做到這一點。 基本上我有一個用組合框填充的變量,然后通過 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
采用
$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);
其他幾個答案提到了 SQL 注入的風險,有幾個答案明確提到了使用准備好的語句,但沒有一個明確說明如何做到這一點,這對初學者來說可能是一個很大的要求。
我目前解決這個問題的首選方法是使用 MySQL 的“IF”語句來檢查有問題的參數是否為空/空/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
而只需要綁定一次。
當然,
$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
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
。
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) );
大優勢:即使子句數組完全為空,查詢語法也是有效的。
首先,請閱讀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.
我想到了另外兩種方法來解決這個問題:
SELECT * FROM moth_sightings
WHERE
user_id = '$username'
AND location = '%$value1%'
AND english_name = $value2 ";
這將僅返回此user_id
結果,其中 location 字段包含$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
的位置或具有空白值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.