如果出现错误,如何让PHP多查询继续执行

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这样的任何内容。我该怎么做?


我没有看到任何地方定义了$test。或者它调用的任何方法。如果我们不知道你的代码在做什么,那就无法提供帮助。 - Kyle
$test = new mysqli("localhost","root","","testdatabase"); $test是一个新的mysqli对象,它连接到名为testdatabase的数据库,用户名为root,主机为localhost。 - user1648409
如果SQL错误是可能的、预期的结果,那么你做的肯定有问题。而且,如果你在使用SQL客户端(或终端),为什么需要一次执行那么多查询? - Andrei Bârsan
2个回答

1
这里的问题可以称为MySQL协议的限制。当使用多个查询(从MySQL的角度来看:将multi statements选项设置为On,然后发送一个查询)时,服务器将拆分它们并逐个执行。答案将被发送而不涉及来源。客户端(在本例中为PHP / mysqli)唯一能够找出错误关联到哪个实际语句的方法是解析完整的查询字符串并尝试进行一些映射。但在许多情况下,这种方法行不通 - 一些语句,特别是CALL,可能会返回多个结果集,无法映射到语句。
如果您想了解更多有关错误的信息,有两个选择:
丑陋的方法是执行$Query = implode(";\n\n",$Query);,然后解析提供的行的错误消息并进行匹配。
或者简单地不使用multi_query。multi_query用于处理返回多个结果集的存储过程调用。在上述情况下使用multi_query只会节省您一点点延迟,因为服务器可以直接处理下一个查询而无需等待下一个查询命令,但即使使用mysqlnd的异步查询操作也可以达到这一点。

-2

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

  • 使用三个单语句
  • 由于您的三个查询非常相似,因此应该使用预处理语句,并使用不同的参数绑定执行三次。这比使用三个单语句提供更好的性能,并使SQL注入变得不可能。
  • 您可以设计一个像这样的通用查询,或者使用UNION进行任何操作:

    "SELECT 'wos' FROM items WHERE itemID IN ('3', '5')"
    
如果你现在认为“这个人在说什么?这将不再是原子性的了。”那么你应该使用一个事务...

这将不再是原子性的了。multi_query 也不是原子性的。 - johannes
@johannes:是的,但你可以这样想。 - Francois Bourgeois

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接