【问题标题】:Trying to understand php mysqli multi_query试图理解 php mysqli multi_query
【发布时间】:2020-11-29 05:16:02
【问题描述】:

我有一个功能,旨在借助 sql 查询复制具有所有属性的产品。 我的问题是完成后将new_product_id返回给php。

如果我在 phpmyadmin 中运行 sql 脚本,一切正常。 如果我用 php 函数运行 sql 脚本,一切正常。

我需要帮助的是如何将 mysql-set-variable: @new_product_id 从最后一个查询分配给我想要返回的 php 变量。

--sql查询------

CREATE TEMPORARY TABLE tmptable SELECT * FROM product WHERE id='19' AND site_id='1';
UPDATE tmptable SET id = 0,parent_id='19',status_id='1',name_internal=concat('NEW ',name_internal);
INSERT INTO product SELECT * FROM tmptable;
SET @new_product_id = LAST_INSERT_ID();
DROP TABLE tmptable;

CREATE TEMPORARY TABLE tmptable SELECT * FROM product_abcd WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = @new_product_id,id=0;
INSERT INTO product_abcd SELECT * FROM tmptable;
DROP TABLE tmptable;

CREATE TEMPORARY TABLE tmptable SELECT * FROM product_efgh WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = @new_product_id,id=0;
INSERT INTO product_efgh SELECT * FROM tmptable;
DROP TABLE tmptable;

(Here is more correct SQL insert statements)

SELECT @new_product_id AS new_product_id;

--sql查询------

-- php函数(不完整)------ 此功能正在制作产品的新副本,下面的代码不完整但有效,因此请只关注多查询部分。

//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
 $res=0;
 //if something, build sql-query as 
 $sql="sql from above";
 //if we have a query to run
 if(!empty($sql)){
  //this is multi query, use correct function
  if ($this->connect()->multi_query($sql) === TRUE) {
  //loop it 
   while ($this->connect()->more_results()){
    $result=$this->connect()->next_result();
   }//while more results
 }//if multiquery ok
return $res;
}//end function copy

--php函数(不完整)------

以上代码有效,我得到了一份不错的产品副本 结果 = 0 表示失败并且 结果 1 表示成功,(这有效)

我希望它如何工作 结果 = 0 表示失败并且 结果 = new_product_id 成功 这样我就可以将用户重定向到新创建的产品,从而一键保存用户。

查询结果,phpmyadmin 与 php 相同(目前一切正常,目前没有错误查询)

  1. Mysql 返回空结果(无行)(创建临时表)
  2. 1 行受影响(更新 tmpt 表)
  3. 1 行插入(插入产品中)
  4. mysql 返回 emtpy 结果(设置 $new_product_id)
  5. mysql 返回空结果(删除 tmp 表)
  6. mysql 返回空结果(创建临时表)
  7. mysql x 行受影响(更新 tmp 表)
  8. mysql x 行受影响(插入表中)
  9. mysql 返回空结果(drop table tmptable)
  10. mysql 返回空结果(创建临时表) .... N....... 最后一个查询“显示第 0-0 行(共 1 行)(选择 @new_product_id) new_product_id=25

我尝试了什么? 我将选择变量作为我的最终查询,我认为它很聪明,只检查最后一个查询并在那里分配变量,但由于 php mysqli fetch_assoc 在非对象上是不可能的,我失败了。

所以接下来不是那么亮,我知道我有 16 个来自 mysql 的结果,我只需要其中一个的结果,但无论如何我把它放在 multiquery 中

-- php函数(不完整)------ 此功能正在制作产品的新副本无法分配 new_product_id

//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
 $res=0;
 //if something, build sql-query as 
 $sql="sql from above";
 //if we have a query to run
 if(!empty($sql)){
  //this is multi query, use correct function
  if ($this->connect()->multi_query($sql) === TRUE) {
  //loop it 
   while ($this->connect()->more_results()){
    //insert,update,drop will return false even if sql is ok, this would be sufficient for us now
    if ($result = $this->connect()->store_result()) {
     $row = $result->fetch_assoc();
     if(isset($row["new_product_id"])){
      //new return value of newly copied product
      $res=$row["new_product_id"];
      $result->free();
     }
    }
    $result=$this->connect()->next_result();
   }//while more results
 }//if multiquery ok
return $res;
}//end function copy

--php函数(不完整)------

在 stackoverflow 上检查其他问题建议发送多个正常查询,当 multi_query 存在时,这似乎是一个糟糕的解决方案。

检查多查询的 php 库对我没有好处,我无法理解它是如何工作的,正如许多其他人指出的那样,文档似乎是另一个函数的副本。

【问题讨论】:

  • 写一个清晰的问题做得很好。欢迎来到堆栈溢出。希望我们能看到您的更多贡献。
  • 没有人提到连接。连接保持不变。说到常见的解决方案,每个查询通常使用单个查询调用单独执行。这就是数据库 API 的工作方式
  • 您可以定义一个数组并在循环中运行您的查询
  • 更好的是,重新思考那堵 SQL 代码。它做了一些非常奇怪的事情。所有这些 SQL 的最终目标是什么?
  • 好吧,我不知道货币联盟与您的数据库结构有什么关系(它是否也规范了您必须使用的 PHP 语法?)但至少编写一个运行这四个查询的函数例程,并调用此函数而不是重复的命令墙

标签: php mysql mysqli mysqli-multi-query


【解决方案1】:

请记住,multi_query() 向 MySQL 服务器发送了一组 SQL 查询,但只等待第一个查询的执行。如果您想使用multi_query() 执行 SQL 并只获取最后一个查询的结果而忽略前面的查询,那么您需要执行一个阻塞循环并将结果缓冲到 PHP 数组中。遍历等待 MySQL 处理每个查询的所有结果,一旦 MySQL 响应没有更多结果,您可以保留最后获取的结果。

例如,考虑这个函数。它将一堆连接的 SQL 查询发送到 MySQL 服务器,然后等待 MySQL 一个一个地处理每个查询。每个结果都被提取到 PHP 数组中,并从函数返回最后一个可用的数组。

function executeMultiQueryAndGetOnlyLastResult(mysqli $mysqli):array {
    $mysqli->multi_query('
    SELECT "a";
    SELECT 2;
    SELECT "val";
    ');

    $values = [];

    do {
        $result = $mysqli->use_result();
        if ($result) {
            // process the results here
            $values = $result->fetch_all();
            
            $result->free();
        }
    } while ($mysqli->next_result()); // next_result will block and wait for next query to finish on MySQL server
    $mysqli->store_result(); // Needed to fetch the error as exception

    return $values;
}

显然,将每个查询单独发送到 MySQL 会容易得多。 multi_query() 非常复杂,用途非常有限。如果您有许多无法通过 PHP 单独执行的 SQL 查询,它会很有用,但大多数时候您应该使用准备好的语句并分别发送每个查询。

【讨论】:

  • 谢谢@dharman 写得很好的回复,你会建议我写15 个单独的$sql 变量,然后在常规的mysqli-> 查询中循环它们吗?它与我们在学校学到的相反。正如我在第一个问题中所写的那样,我花了几个小时寻找解决方案,其中大多数建议使用单个查询。
  • 是的,总是尝试单独执行它们。大多数时候你会想使用准备好的语句而不是query,但我认为在这种情况下它并不重要。
【解决方案2】:

另一个尘埃落定,我放弃并定义了一个从 0 到 14 的 sql 查询数组,并将其作为 mysqli->query() 运行。感谢大家的 cmets 和您的时间。

【讨论】:

  • 从这条评论来看,“Here is more correct SQL insert statements”应该超过14条?
  • @YourCommonSense 是的,取决于一个变量,可能还有更多行
【解决方案3】:

您可以尝试对操作中的所有查询使用.multi_query(),除了最后一个查询,即返回您想要的 id 的 SELECT。然后将该 SELECT 作为单个查询运行。

这是解决您的问题的可靠解决方案:@-variables 属于 MySql 连接并在这些连接的生命周期内持续存在。

而且,它可以让您的软件运行干净且可预测。当您需要将结果集返回给您的程序时,请使用单个查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 2011-06-20
    • 2018-11-22
    • 2018-04-13
    • 2011-12-14
    • 1970-01-01
    • 2013-06-23
    • 2012-01-25
    相关资源
    最近更新 更多