【问题标题】:Use prepared statement in query with 'IN(.....)' clause?在带有“IN(.....)”子句的查询中使用准备好的语句?
【发布时间】:2011-05-20 14:04:50
【问题描述】:

是否有(棘手/非标准)方法可以做到这一点?

想要什么

$stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN (?, ?, ?, ?);

工作?因此,如果我想搜索可变数量的 id,我可以这样做吗

$ids = array(1,2,3,4,5,6,7);
$idSection = implode(array_pad(array(), count($ids), '?')) //To give ?,?,?,?,?,?,?
$stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN ($idSection);
$stmp->execute($ids);

即使这样可行,它对于使用相同的预准备语句运行多组数据仍然没有真正的用处,除非每次搜索的 $ids 集的长度都相同并且它不适用命名占位符。

我假设你这样做

$stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN (:ids);
$ids = implode('","' array(1,2,3,4,5,6,7));
$stmt->bindParam( ':ids', $ids);

它失败了,因为准备好的语句被构造成它将搜索单个 id 值,并且 "1","2","3","4","5","6","7" 不会不匹配?

我确信有比不使用IN(...) 子句更好的答案。我是否只需要手动清理 $ids 术语并将其包含在不带占位符的查询中?

$stmt = $db->prepare( "SELECT title FROM episode WHERE id IN $ids AND genre like :genre");
$stmt->bindParam( ':genre', '%$genre%);

【问题讨论】:

    标签: php pdo


    【解决方案1】:

    MySql 有一个 FIND_IN_SET 函数,你可以使用它来达到相同的结果:

    $ids = array(1,2,3,4,5,6,7);
    $stmt = $db->prepare( 'SELECT title FROM episode WHERE FIND_IN_SET(id,?)' );
    $param = implode(',',$ids);
    $stmt->bind_param('s',$param); 
    $stmt->execute(); 
    

    【讨论】:

    • 请记住,与 IN 子句相比,FIND_IN_SET 非常慢
    【解决方案2】:

    避免使用 IN 子句的一种方法是使用将作为逗号分隔列表进入 IN( ... ) 的值填充临时表;然后在临时表的列上进行 INNER-JOIN 或进行嵌套选择:

            inner join temptable T2 on T1.mycol = T2.col1
    

           ...  where mycol in ( Select col1 from temptable)
    

    【讨论】:

    • 这是个好主意!但由于我试图以“准备好的方式”做事,那么我要么必须运行准备好的多插入语句来构建临时表(遇到相同类型的问题),要么运行准备好的单插入语句多次。我知道多次运行准备好的单次插入应该比多次运行常规的单次插入要快,但它仍然会比多次插入慢得多吗?
    • 取决于行数,但多次运行准备好的语句是更好的做法。您可以将一个简单的分隔字符串传递给服务器上的存储过程,该过程从字符串中提取组成值并插入到临时表中。
    猜你喜欢
    • 2023-02-16
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 2012-05-24
    相关资源
    最近更新 更多