【问题标题】:mysqli_multi_query: need to check single result?mysqli_multi_query:需要检查单个结果吗?
【发布时间】:2018-02-01 10:52:06
【问题描述】:

我正在使用此代码插入具有唯一 id 的记录,然后返回刚刚创建的 id 字符串:

$sql ="set @id=UUID();";
$sql .="INSERT INTO `items` (`id`,`parent`, `text`, `type`) VALUES(@id,'".$parent."', '".$text."', '".$type."');";
$sql .="select @id;";


if (mysqli_multi_query($conn, $sql)) {
  while (mysqli_more_results($conn)) {
    mysqli_use_result($conn);
    mysqli_next_result($conn);
  }//while

  $result = array('id' => mysqli_store_result($conn)->fetch_row()[0]);

  }//if

如果一切正常,三个查询应该返回:

  1. 1/真(我猜)
  2. 1/真
  3. 对象

我以前从未使用过这个函数,我想知道:如果插入查询失败会发生什么?

第三个查询还会执行吗?

在这种情况下,我如何检查第二个查询的结果?

编辑:

或者一般来说:

有一组 10 个查询,如果失败,我如何检查哪个查询失败了?

【问题讨论】:

  • “有一组 10 个查询,如果失败,我如何检查哪个查询失败了?” - mysqli_multi_query 的引用手册:“如果返回 FALSE第一条语句失败。要从其他语句中检索后续错误,您必须先调用 mysqli_next_result()。”
  • 嗯,这很奇怪,因为经过一些测试,查询失败似乎停止了下一个查询的执行......如果没有下一个结果,我怎么能得到下一个结果? (WTF) 我猜它的目的是:如果第一个查询没问题,那么使用 mysqli_next_result 转到下一个。 (?)

标签: php mysqli


【解决方案1】:

经过一番测试……

假设我们有以下 3 个查询:

$sql ="INSERT INTO `items` (`id`,`parent`) VALUES ('id',WRONG_NO_QUOTES);";
$sql .="INSERT INTO `items` (`id`,`parent`) VALUES ('id','right2');";
$sql .="INSERT INTO `items` (`id`,`parent`) VALUES ('id','right3');";

使用手册提供的代码...

if (mysqli_multi_query($conn,$sql)) {
    do {
        /* store first result set */
        if ($result = mysqli_store_result($conn)) {
            while ($row = $result->fetch_row()) {
                printf("%s\n", $row[0]);
            }
            $result->free();
        }
        /* print divider */
        if (mysqli_more_results($conn)) {
            printf("-----------------\n");
        }
    } while (mysqli_next_result($conn));
}
//...plus this....
if(mysqli_errno($conn)){
        echo 'mysqli_errno:';
        var_dump(mysqli_errno($conn));
        echo'<br>';
    }

...输出是:

mysqli_errno:
[...]test.php:39:int 1146

...数据库没有任何变化。

结论:

发生错误时,不会执行下一个查询。 并且可以在 do/while 循环结束时轻松捕获错误。

编辑

上面的代码会生成一个严格的标准通知。

我对其进行了编辑以避免通知并获得错误的(基本)回溯:

$n=1;
$i=1;
if (mysqli_multi_query($conn,$sql)) {
    do {
        /* store first result set */
        if ($result = mysqli_store_result($conn)) {
            while ($row = $result->fetch_row()) {
                echo $row[0];
            }
            $result->free();
        }
        /* print divider */
        if (mysqli_more_results($conn)) {
            echo "<hr>";
            $n++;
            mysqli_next_result($conn);
        }else{$i=0;}
    } while ($i>0);
}
if(mysqli_errno($conn)){
  echo 'mysqli error on query number '.$n;
  var_dump(mysqli_errno($conn));
}

【讨论】:

    【解决方案2】:

    由于我的实际问题是避免查询之间的竞争并获得正确的标识符(检查:this question),我意识到有一种更简单(也许更好)的方法来达到预期的结果(这里使用 pdo 扩展):

    $db = new PDO ("mysql:host=$hostname;dbname=$dbname", $user, $pass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    
    //No user defined variable here inside (safe)
    $identifier=db->query("SELECT UUID();")->fetch()[0];
    

    将标识符存储到 PHP 变量中,然后我可以使用 pdo 和prepared statements 分别处理每个后续查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 2020-12-03
      • 1970-01-01
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多