在 运行 时间构建多个 LIKE 运算符准备语句

Building Multiple LIKE Operator Prepared Statement at run-time

Table tbl
col1 | | col3

SQL 我想使用 with prepared statement 并在运行时绑定参数

select col1, col2, col3 
from tbl 
where col1=10 
and col2 between 0 and 10 and col3 like '%QUERY%';

问题是对 col3 的过滤取决于用户输入。如果只使用 2 个术语,那么它应该是

select col1, col2, col3 
from tbl 
where col1=10 
and col2 between 0 and 10 and (col3 like '%QUERY%' AND col3 like '%QUERY2%');

如果找到 3 个输入,那么它应该是

select col1, col2, col3 
from tbl 
where col1=10 
and col2 between 0 and 10 and (col3 like '%QUERY%' AND col3 like '%QUERY2%' AND col3 like '%QUERY3%');

我只想使用 Prepared Statement 而不是直接查询。我知道同样可以通过清理输入和 运行 直接查询来实现,但我仍然只喜欢准备好的语句。

如何实现?

在我的代码下面:(打开SQL注入

$terms=explode(",",$_POST['txtD']);
$sql='';                     
for($i=0;$i<count($terms);$i++) {
    $terms[$i] = trim($terms[$i]);
    if ($i!=$count-1)
        $sql = $sql."`Places` LIKE '%$terms[$i]%' AND ";
    else
        $sql = $sql."`Places` LIKE '%$terms[$i]%'";
}

$stmt = mysqli_prepare($con,"select col1, col2, col3 from tbl where col1=? and col2 between ? and ? and ".$sql);
mysqli_stmt_bind_param($stmt,"iii", $param1, $param2, $param3);
mysqli_stmt_execute($stmt); 
mysqli_stmt_close($stmt);

考虑使用 implode 构建准备好的 SQL 语句的 LIKE 表达式部分。然后构建一个参数参数为 运行 和 call_user_func_array().

$terms = explode(",", str_replace(",", " ,", $_POST['txtD']));

// PREPARED STATEMENT BUILD
$likes = [];
foreach($terms as $t) {
    $likes[] = "col3 LIKE CONCAT('%', ?, '%')";
}

$expr = implode(" or ", $likes);
$sql = "select col1, col2, col3 from tbl ".
       "where col1=? and col2 between ? and ? and (". $expr .")";

// PARAM ARG BUILD
$type = 'iii' . str_repeat("s", count($terms));
$sql_params = array_merge(array($stmt, $type, $param1, $param2, $param3), $terms);

// PREPARE AND EXECUTE QUERY
$stmt = mysqli_prepare($con, $sql);
call_user_func_array('mysqli_stmt_bind_param', sql_params);    
mysqli_stmt_execute($stmt); 
mysqli_stmt_close($stmt);

SQL and Param Build Demo


或者,考虑 MySQL 的 REGEXP 正则表达式,使用管道表示 OR 逻辑:

// REPACE COMMAS BY PIPE
$terms = str_replace(",", "|", str_replace(",", " ,", $_POST['txtD']));

$sql = "select col1, col2, col3 from tbl " .
       "where col1=? and col2 between ? and ? and col3 regexp ?";

// PREPARE AND EXECUTE QUERY
$stmt = mysqli_prepare($con);    
mysqli_stmt_bind_param($stmt, "iii", $param1, $param2, $param3, $terms);
mysqli_stmt_execute($stmt); 
mysqli_stmt_close($stmt);

如前所述请注意 here REGEXP 的执行速度比等效的 LIKE 表达式要慢。