详解php mysqli扩展中的方法multi_query的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhang197093/article/details/52658665

php的mysqli扩展中有一个一次执行多条sql语句的方法 multi_query,先看看官方的解释:

Executes one or multiple queries which are concatenated by a semicolon.

To retrieve the resultset from the first query you can use mysqli_use_result() or mysqli_store_result(). All subsequent query results can be processed using mysqli_more_results() and mysqli_next_result()

多条sql用分号连接,先看个简单的示例:

<?php
$mysqli= new mysqli('localhost', 'root', '', 'test');

$sql = "INSERT INTO user (name,age) VALUES ('admin', 26); ";
$sql .= "UPDATE user SET age = 30 WHERE name = 'root'; ";
$sql .= "SELECT name,age FROM user LIMIT 10";

if ($mysqli->multi_query($sql))
{
    do {

        $res = $mysqli->store_result();

        if ($res instanceof mysqli_result)
        {
            //select 查询
            while ($row = $res->fetch_assoc())
            {
                //...
            }
        }
        else
        {
            //insert update delete查询
        }

    } while ($mysqli->more_results() && $mysqli->next_result());  //调用next_result()之前必须调用more_result()
}

下面关于该函数的一些使用细节做一下介绍。


一、为什么多次使用multi_query只有第一次成功,后面的都失败了

这是因为使用multi_query之后必须释放掉它的查询结果,否则之后的查询都会失败,也就是需要不停调用next_result()直到最后一个结果,如果对查询结果并不关心,可以简单的像这样处理。


    while ($mysqli->more_results() && $mysqli->next_result())
    {
        //什么也不做
    }

二、怎么判断每条sql语句是否执行成功了

这可能是大家对该函数最困惑的地方了,对照一开始的示例,根据经验大家可能会觉得对于select的查询结果,如果返回的是一个结果集,查询就是成功的,而对于 insert/update/delete 这样的查询,如果返回false就是失败的。

由于我们每条sql的结果是调用store_result()得到的,先看下手册中对于store_result()方法的介绍:

Note:

mysqli_store_result() returns FALSE in case the query didn't return a result set (if the query was, for example an INSERT statement). This function also returns FALSE if the reading of the result set failed. You can check if you have got an error by checking if mysqli_error() doesn't return an empty string, if mysqli_errno() returns a non zero value, or if mysqli_field_count() returns a non zero value. Also possible reason for this function returning FALSE after successful call to mysqli_query() can be too large result set (memory for it cannot be allocated). If mysqli_field_count() returns a non-zero value, the statement should have produced a non-empty result set.


这地方提到了,如果一条sql查询没有返回结果集,那么store_result()就会返回false,所以对于 insert/update/delete 这样的查询返回的永远是false, 而不管是否查询成功,口说无凭,实践是检验真理的唯一标准,我们仍旧以开始的例子做演示。




把一开始的示例稍作修改,输出每条查询结果的信息

<?php
$mysqli= new mysqli('localhost', 'root', 'root', 'test');

$sql = "INSERT INTO user (name,age) VALUES ('admin', 26); ";
$sql .= "UPDATE user SET age = 30 WHERE name = 'root'; ";
$sql .= "SELECT name,age FROM user LIMIT 10";

if ($mysqli->multi_query($sql))
{

    do {

        $res = $mysqli->store_result();
        var_dump($res); //输出信息

        if ($res instanceof mysqli_result)
        {
            //select 查询
            while ($row = $res->fetch_assoc())
            {
                //...
            }
        }
        else
        {
            //insert update delete查询
        }

    } while ($mysqli->more_results() && $mysqli->next_result());  //调用next_result()之前必须调用more_result()
}


然后在命令行中执行php脚本,结果如下:



可以看到第1和第2条返回的结果都是false,但第三条查询结果可以看到num_rows是2,说明之前的insert语句执行成功了,看看执行之后的查询结果。



那么是不是就没有判断是否成功的方法呢,别忘了mysqli有errno和error可以获取最近一次查询的错误号和错误信息,再来看看手册中对于multi_query中的一个note:

Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to callmysqli_next_result() first.

如果第一条语句失败,则multi_query的返回结果就是false,而要得到随后语句的查询错误,必须先调用mysqli_next_result()方法,那么最开始的示例就可以修改如下了:

<?php
$mysqli= new mysqli('localhost', 'root', 'root', 'test');

$sql = "INSERT INTO user (name,age) VALUES ('admin', 26); ";
$sql .= "UPDATE user SET age = 30 WHERE name = 'root'; ";
$sql .= "UPDATE user SET gender = 'male' WHERE NAME = 'root'; "; //这句执行结果会报错, 没有gender字段
$sql .= "SELECT name,age FROM user LIMIT 10";

if ($mysqli->multi_query($sql))
{
    while (TRUE)
    {
        echo 'error:  ' . $mysqli->errno . ' -- ' . $mysqli->error . "\n";

        $res = $mysqli->store_result();
        var_dump($res);

        if ($res instanceof mysqli_result)
        {
            //select 查询
            while ($row = $res->fetch_assoc())
            {
                //...
            }
        }
        else
        {
            //insert update delete查询
        }

        if (!$mysqli->more_results())
        {
            break;
        }

        $mysqli->next_result();
    }
}




并且可以看出,某条语句查询出错,则之后的语句就不再执行。


三、multi_query和单条依次查询的效率比较

由于篇幅有限,这个效率比较将会放在下一遍文章,今天就写到这里,谢谢大家关注。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页