我有一个使用HTML的常用搜索表单,它将从mysql中提取数据(连接使用PHP和mysqli)。该函数在搜索1值时效果很好,但我想让用户可以搜索多个用逗号(,)分隔的值。
但我想在搜索框中搜索2个或更多值,例如: 42-7278954,53-1217544,07-2517487,...
我希望用户可以输入如下图所示的内容,结果将有2行 - > CN_no 42-7278954 和 53-1217544 :
我到目前为止的查询是:
$sql = "SELECT * FROM mock_data WHERE CN_no IN ('{$CN_no}') OR doc_no IN ('{$doc_no}')";
注意:CN_no是"货件代码"和doc_no是"参考号"
但是好吧......由于语法不正确,显然会给我一个错误。
请帮我修改一下。谢谢。
========根据vp_arth的回答更新查询========
$cn = explode(',', $CN_no);
$incn = str_repeat('?, ', count($cn)-1).'?';
$doc = explode(',', $doc_no);
$indoc = str_repeat('?, ', count($doc)-1).'?';
$query = "SELECT * FROM mock_data WHERE CN_no IN ({$incn}) or doc_no IN ({$indoc})";
$result = $conn->query($query , array_merge($incn, $indoc));
但它给了我一个error
答案 0 :(得分:2)
这是在prepared statements
中使用mysqli
和动态输入的可能解决方案。 parameter binding
的输入是静态的,在这种情况下参数是strings
。
/**
* connecting to the database
* defining in how manye columns you want to search (important to create the correct amount of arguments)
*/
$conn = new mysqli('localhost', 'root', '', 'test');
$columnsToSearch = 2;
/**
* the numbers you want to search delimited by ","
*/
$CN_no = '42-7278954,53-1217544,07-2517487';
$cn = explode(',', $CN_no);
/**
* writing the numbers to search into variables
* putting the references of those variables into an array
*
* the references will be used as arguments for the prepared statement
*/
$values = array();
for ($i = 0; $i < $columnsToSearch; $i++) {
foreach ($cn as $k => $value) {
$temp{$k}{$i} = $value;
$values[] = &$temp{$k}{$i};
}
}
/**
* putting together the "types"-part for the binding of the prepared statement
*/
$types = array(str_repeat('s', count($cn) * $columnsToSearch - 1) . 's');
/**
* merging types and references
*/
$argumentsArray = array_merge($types, $values);
/**
* creating placeholder string for the query
*/
$placeholder = str_repeat('?, ', count($cn) - 1) . '?';
$stmt = $conn->prepare('SELECT CN_no, doc_no FROM mock_data WHERE CN_no IN (' . $placeholder . ') or doc_no IN (' . $placeholder . ')');
/**
* check http://us3.php.net/manual/en/mysqli-stmt.bind-param.php#104073 to read what is happening here
*/
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt, $argumentsArray);
$stmt->execute();
/**
* fetching the result
*/
$stmt->bind_result($CN_no, $doc_no);
$row_set = array();
while ($row = $stmt->fetch()) {
$row_set[] = array('CN_no' => $CN_no, 'doc_no' => $doc_no);
}
var_dump($row_set);
exit;
我调整了http://us3.php.net/manual/en/mysqli-stmt.bind-param.php#104073的评论,因此它符合您的情况。
顺便说一下。使用PDO
作为数据库API,这将更容易编写和阅读。我稍后可能会为PDO
添加一个示例。
答案 1 :(得分:2)
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
// search input
$input = '42-7278954,53-1217544,07-2517487';
// create and filter your search array
$iArr = array_filter(array_map('trim', explode(",", $input)), 'strlen');
// create your search string from CN_no array
$CN_no = implode("|",$iArr);
/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT * FROM `mock_data` WHERE `CN_no` RLIKE ?")) {
/* bind parameters for search */
$stmt->bind_param("s", $CN_no);
/* execute query */
$stmt->execute();
// get all the rows returned
// IMPORTANT
// Use the below syntax in case you do use native mysqlnd driver.
// If you don't have mysqlnd installed/loaded, you will get an error
// that "mysqli_stmt_get_result()" method is undefined.
$result = $stmt->get_result()->fetch_all();
// in case you don't have native mysqlnd loaded uncomment
// and try the below syntax to get the result
/* $meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $params);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$c[$key] = $val;
}
$result[] = $c;
} */
/* *********** */
// print output
print_r($result);
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
答案 2 :(得分:0)
$input = '42-7278954,53-1217544,07-2517487';
$inputs = explode(',', $input);
$new_inputs = array_map(function ($item){
$item = trim($item);
return "'" . $item . "'";
}, $inputs);
$string = implode(',', $new_inputs);
// string is '42-7278954','53-1217544','07-2517487'
$sql = "SELECT * FROM mock_data WHERE CN_no IN ({$string})";
答案 3 :(得分:0)
一些抽象的PHP代码:
$cn = explode(',', $input1);
$incn = str_repeat('?, ', count($cn)-1).'?'
$doc = explode(',', $input2);
$indoc = str_repeat('?, ', count($doc)-1).'?'
$sql = "SELECT ... WHERE cn_no IN ({$incn}) or doc_no IN ({$indoc})";
$result = $db->rows($sql, array_merge($cn, $doc));
答案 4 :(得分:0)
使用FIND_IN_SET()
功能
语法:FIND_IN_SET(YOUR_INPUT_STRING_NAME,COLUMN_NAME);
YOUR_INPUT_STRING_NAME,可能是42-7278954,53-1217544,07-2517487,...
让我知道它是否对你有所帮助。
答案 5 :(得分:0)
$input = '42-7278954,53-1217544,07-2517487';
echo $strNew=str_replace(",","','",$input);
$sql = "SELECT * FROM mock_data WHERE CN_no IN ('".$strNew."')";
$row=mysqli_query($conn,$query)or die("not fire");
试试这段代码
答案 6 :(得分:0)
似乎in-clause没有通过您的实现正确生成。
要正确生成子句,您需要将用户输入拆分为数组,然后再加入列表中。例如,如果用户已将42-7278954,53-1217544,07-2517487作为输入,则列表内应如下所示:
negative
鉴于货件代码和参考代码是字符串值,您必须将它们用引号括起来&#39; & #39; 强>
以下示例可以帮助您使用implode和explode生成列表表达式(我很少知道php)
CN_No in ( '42-7278954' , '53-1217544' , '07-2517487');
希望这有帮助。
此外,正如其他人所述,您可能需要清理用户输入以防止SQL-Injection攻击。
答案 7 :(得分:-2)
尝试
$cn = explode(',', $CN_no);
$incn = str_repeat('?, ', count($cn)-1).'?';
$doc = explode(',', $doc_no);
$indoc = str_repeat('?, ', count($doc)-1).'?';
$query = "SELECT * FROM mock_data WHERE CN_no IN ('.$incn.') or doc_no IN ({$indoc})";
$result = $conn->query($query , array_merge($incn, $indoc));
答案 8 :(得分:-3)
根据原始查询,您可以将其更改为将构建搜索数据集
$CN_no = explode(",", $CN_no);
$CN_no = "'".implode("','", $CN_no)."'";
$doc_no = explode(",", $doc_no);
$doc_no = "'".implode("','", $doc_no)."'";
$sql = "SELECT * FROM mock_data WHERE CN_no IN ({$CN_no}) OR doc_no IN ({$doc_no})";