代码之家  ›  专栏  ›  技术社区  ›  Ed Marty

我可以使用MYSQLI和PHP将多个值绑定为单个参数吗?

  •  2
  • Ed Marty  · 技术社区  · 14 年前

    SELECT id,name FROM user WHERE id IN ('id1','id2','id3')
    

    现在假设我需要PHP提供id数组。所以我有这样的想法:

    $idList = array('id1','id2','id3');
    $query = "SELECT id,name FROM user WHERE id IN (?)";
    $stmt = $db->prepare($query);
    $stmt->bind_param(/*Something*/);
    

    我能替换什么 /*Something*/

    4 回复  |  直到 14 年前
        1
  •  1
  •   webbiedave    14 年前

    参数使用MYSQLI和PHP?

    对于您的情况,应该以编程方式构建查询字符串。如果保证它总是三个值,那么可以向SQL添加三个标记,然后通过在数组上循环进行绑定。

        2
  •  5
  •   Fanis Hatzidakis    14 年前

    ? str_repeat() bind_param

    注意str\u repeat将返回的尾部逗号。或者 rtrim() 或者使用 array_fill() 创建重复占位符数组,然后 join()

    $arrPlaceholders = array_fill(0, count($idList), '?') ;
    $strPlaceholders = join(', ', $arrPlaceholders) ;
    

    那么您的查询可以是:

    $query = "SELECT id,name FROM user WHERE id IN ($strPlaceholders)";
    

    您可以将参数绑定到一个循环中。

        3
  •  1
  •   marc_s    9 年前

    这可能有点老了,但我自己也在想。所以我做了一个基准测试。首先,我创建了一个简单的表:

    SELECT * from random LIMIT 10;
    +----+------------+
    | id | rand_stuff |
    +----+------------+
    |  1 | 1988585319 | 
    |  2 | 1926594853 | 
    |  3 |  820681972 | 
    |  4 |  950331574 | 
    |  5 |  540721998 | 
    |  6 | 1284256353 | 
    |  7 |   12804417 | 
    |  8 | 2130482967 | 
    |  9 | 2018786156 | 
    | 10 |  285818156 | 
    +----+------------+
    
    SELECT count(id) from random;
    +-----------+
    | count(id) |
    +-----------+
    |   3365586 | 
    +-----------+
    
    /var/lib/mysql/benchmark# ls -laFh
    total 101M
    drwx------ 2 mysql mysql 4.0K 2011-05-28 00:06 ./
    drwxr-xr-x 7 mysql mysql 4.0K 2011-05-27 23:53 ../
    -rw-rw---- 1 mysql mysql   65 2011-05-27 23:53 db.opt
    -rw-rw---- 1 mysql mysql 8.4K 2011-05-28 00:06 random.frm
    -rw-rw---- 1 mysql mysql  55M 2011-05-28 00:32 random.MYD
    -rw-rw---- 1 mysql mysql  47M 2011-05-28 00:32 random.MYI
    

    它是一个微不足道的结构,重约100 MB。这个随机数是用php的mt\u rand()函数创建的。

    “这是”获取.php":

    <?php
    
    $loops = $argv[1];
    
    $mysqli = new mysqli("localhost", "bench", "bench", "benchmark");
    if(mysqli_connect_errno()){
        printf("Connect Failed: %s\n", mysqli_connect_error());
        exit();
    }
    
    if($stmt = $mysqli->prepare("SELECT rand_stuff FROM random WHERE id = ?")){
        for($i=1; $i<$loops; $i++){
            $stmt->bind_param("i", $i) or die;
            $stmt->execute() or die;
            $stmt->bind_result($value) or die;
            $stmt->fetch();      
            echo "$i \t $value\n";
        }
        $stmt->close();
    }
    

    以及一些基准:

    $time php fetch.php 10 > /dev/null
    
    real    0m0.043s
    user    0m0.024s
    sys 0m0.012s
    
    $ time php fetch.php 100 > /dev/null
    
    real    0m0.057s
    user    0m0.044s
    sys 0m0.000s
    
    $ time php fetch.php 1000 > /dev/null
    
    real    0m0.166s
    user    0m0.080s
    sys 0m0.012s
    
    $ time php fetch.php 10000 > /dev/null
    
    real    0m1.083s
    user    0m0.412s
    sys 0m0.124s
    

    下面是fetch2.php

    <?php
    
    $loops = $argv[1];
    
    $mysqli = new mysqli("localhost", "bench", "bench", "benchmark");
    if(mysqli_connect_errno()){
        printf("Connect Failed: %s\n", mysqli_connect_error());
        exit();
    }
    
    $array = array();
    
    for($i=1; $i<$loops; $i++){
        $array[] = $i;
    }
    
    $joined_array = join($array, ',');
    
    $results = $mysqli->query("SELECT id, rand_stuff FROM random WHERE id IN ($joined_array)");
    
    while($row = $results->fetch_row()){
        $val1 = $row[0];
        $val2 = $row[1];
        echo "$val1\t$val2\n";
    }
    

    以下是它的相关基准。

    $time php fetch2.php 10 > /dev/null
    
    real    0m0.037s
    user    0m0.028s
    sys 0m0.008s
    
    $time php fetch2.php 100 > /dev/null
    
    real    0m0.044s
    user    0m0.032s
    sys 0m0.008s
    
    $ time php fetch2.php 1000 > /dev/null
    
    real    0m0.050s
    user    0m0.036s
    sys 0m0.016s
    
    
    $ time php fetch2.php 10000 > /dev/null
    real    0m0.117s
    user    0m0.088s
    sys 0m0.024s
    

    +--------+-----------+------------+
    |  Loop  | Fetch.php | Fetch2.php |
    +--------+-----------+------------+
    | 10     |  .043s    |  .037s     |
    | 100    |  .057s    |  .044s     |
    | 1000   |  .116s    |  .050s     |
    | 10000  | 1.083s    |  .117s     |
    +--------+-----------+------------+
    

    显然,“Fetch2.php”更有效,但是在这个基准测试中。。。在你进入100+元素范围之前,这似乎并不重要。对准备好的语句进行迭代既简单又安全(根本不可能进行SQL注入),而且在~10个元素的范围内似乎不会慢很多。用~10个元素重复测试有时可能会有“获取.php“赢得基准。总的来说,Fetch2.php当然赢了,但它们在这个范围内肯定很接近。

    我倾向于说。。。如果少于100个元素,只需利用准备好的语句并重复执行即可。毕竟,准备好的声明就是为了这个目的而设计的。当然,没有什么比数据库的一次往返更有效了,但是prepared statement方法可能具有可接受的性能。当然,在您自己的系统上进行基准测试。很可能,上面的测试太简单了(没有任何连接或子查询。。。数据库和php脚本在同一个系统上……)