6

我得到了这个代码:

// Some starting variables
$test = new mysqli("localhost","root","","testdatabase");
$Query = array();
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 3";
$Query[] = "SELECT 'wos' FROM items WHERE itemID";
$Query[] = "SELECT 'wos' FROM items WHERE itemID = 5";
$Query = implode(";",$Query);
$Errors = array();

// Execute multi query

if ($test->multi_query($Query)) {
  do {
    // fetch results
    $Result = $test->store_result();
    print_r($Result);
    if($test->errno === 0) {
          echo $Result->num_rows . "<br>";
    }
    else {
        $Errors[] = $test->error;
    }
    $Result->close();
    
    if (!$test->more_results()) {
      break;
    }
    if (!$test->next_result()) {
      $Errors[] = $test->error;
      break;
    }
  } while (true);
}

如您所见,我有许多 X 后续查询,并希望全部执行。因此,如果查询 2 失败,我想继续多查询以让以下查询运行。我怎样才能做到这一点?

另外,如果发生错误,我想将此错误保存在$Errors. 但是,目前它并没有按预期工作,因为我只能保存错误消息而不能保存相应的查询。如果没有失败的查询,只有错误消息并没有真正的帮助。所以我想要类似的东西:"Query 3 failed ('SELECT ...'): 'ERROR MESSAGE'".

这怎么可能?我可以在循环中获取当前错误$test->error,但我没有类似$test->currentsubsequentquery. 我怎样才能做到这一点?

4

2 回答 2

1

这里的问题可以称为 MySQL 协议中的限制。当使用多查询时(从 MySQL 的角度来看:将多语句选项设置为 On 然后发送查询),服务器将拆分它并一个接一个地执行它们。答案将在不参考来源的情况下发送。客户端(在本例中为 PHP/mysqli)可以找出错误与哪个实际语句相关的唯一方法,它必须解析完整的查询字符串并尝试进行一些映射。但这在很多情况下都行不通——一些语句,最值得注意的是CALL,可以返回多个无法映射到语句的结果集。

如果您想了解有关错误的更多信息,有两种选择:

丑陋的人正在做$Query = implode(";\n\n",$Query);,然后解析提供的行的错误消息并匹配它们。

或者干脆不使用multi_query。multi_query 用于处理返回多个结果集的存储过程调用。在上述情况下使用 multi_query 只会为您节省一点点延迟,因为服务器可以直接处理下一个查询而无需等待下一个查询命令,但即使使用 mysqlnd 的异步查询操作也可以达到这一点。

于 2013-01-10T15:29:46.973 回答
-1

好吧,单个语句中的多个查询通常不是一个好主意。好的 SQL 客户端(例如 PDO)根本不允许多个查询,因为这种方式 SQL 注入变得更加困难。我想劝阻您的想法并提出以下解决方案之一:

  • 使用三个单一的语句
  • 由于您的三个查询非常相似,因此您应该使用准备好的语句并使用不同的参数绑定执行三次。这提供了比三个单语句更好的性能,并使 SQL 注入成为不可能。
  • 你可以像这样设计一个对所有的查询,或者用 UNION 做任何事情:

    "SELECT 'wos' FROM items WHERE itemID IN ('3', '5')"
    

如果你现在想“这家伙在说什么?这将不再是原子的。” 那么你应该使用交易......

于 2013-01-10T15:32:57.650 回答