【问题标题】:MySQL Error - Commands out of sync; you can't run this command nowMySQL 错误 - 命令不同步;你现在不能运行这个命令
【发布时间】:2013-04-08 10:13:46
【问题描述】:

我正在使用 MySQL 和 PHP,Codeigniter。我有一个问题,bluefeet 在here@

的帖子中回答了这个问题

我为 bluefeet 的第二个解决方案创建了一个存储过程。它运行良好,但是,在生产环境中调用该过程时,所有其他用户都会收到错误

命令不同步;你现在不能运行这个命令

不知道如何克服这个错误。我还尝试在调用该过程后关闭连接,但是,在关闭连接之前执行来自其他用户的查询。有解决此问题的方法吗?

下面是我用过的存储过程

DROP PROCEDURE IF EXISTS mailbox.circle_pending_p;
CREATE PROCEDURE mailbox.`circle_pending_p`()
BEGIN
SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN maildate = ''',
      date_format(mailtime, '%e-%b'),
      ''' THEN 1 else 0 END) AS `',
      date_format(mailtime, '%e-%b'), '`'
    )
  ) INTO @sql
FROM circle_pending_temp
WHERE mailtime >= (select date_sub(max(mailtime), interval 8 DAY)
                   from circle_pending_temp);

SET @sql 
  = CONCAT('SELECT coalesce(email_Circle, ''Grand Total'') Circle,
              max(`< 9 days`) `< 9 days`, ', @sql, ' ,
              count(*) GrandTotal
            from
            (
              select c.email_Circle,
                date_format(c.mailtime, ''%e-%b'') maildate,
                coalesce(o.`< 9 days`, 0) `< 9 days`
              from circle_pending_temp c
              left join
              (
                select email_Circle,
                  count(*) `< 9 days`
                from circle_pending_temp
                where mailtime <= (select date_sub(max(mailtime), interval 8 DAY)
                                    from circle_pending_temp)
              ) o
                on c.email_Circle = o.email_Circle
              where c.mailtime >= (select date_sub(max(mailtime), interval 8 DAY)
                                      from circle_pending_temp)
            ) d
            group by email_Circle with rollup ');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;

我用来调用这个过程的 PHP 是

    $db = $this->load->database('mailbox',TRUE);
    $res = $db->query('Call circle_pending_p()');
    echo $db->_error_message();
    $db->close();
    $db = $this->load->database('mailbox',TRUE);
    if ($res->num_rows() > 0) {
        return $res->result_array();
    } else {
        return 0;
    }

【问题讨论】:

    标签: php mysql codeigniter stored-procedures pivot


    【解决方案1】:

    当我在循环中运行存储过程时遇到了类似的问题。我使用的以下代码:

    foreach ($month_list as $month_row) 
    {
    
      $start_date = $month_row->adate;
      $end_date = date("Y-m-d", strtotime("last day of " . date("F", strtotime($start_date)) . " " . date("Y", strtotime($start_date))));
    
      $qry_res = $this->db->query("call staff_attendance('$start_date', '$end_date')");
    
      $res = $qry_res->result();
    
      $qry_res->next_result();
      $qry_res->free_result();
    
      $compiled_months[] = $res;
    
    }
    

    在这种情况下,我创建的临时表被抱怨为表已经存在。

    所以,改用这种方法:

    foreach ($month_list as $month_row) 
    {
    
      $start_date = $month_row->adate;
      $end_date = date("Y-m-d", strtotime("last day of " . date("F", strtotime($start_date)) . " " . date("Y", strtotime($start_date))));
    
      $compiled_months[] = $this->db->query("call staff_attendance('$start_date', '$end_date')")->result();
      $this->db->close();
      $this->db->initialize();
    
    }
    

    现在执行很完美

    【讨论】:

      【解决方案2】:

      在文件中

      system/database/drivers/mysqli/mysqli_result.php
      

      添加:

      function next_result()
      {
          if (is_object($this->conn_id))
          {
              return mysqli_next_result($this->conn_id);
          }
      }
      
      function result($type = 'object')
      {
          $result = array();
      
          if ($type == 'array') $result = $this->result_array();
          else if ($type == 'object') $result = $this->result_object();
          else $result = $this->custom_result_object($type);
      
          $this->next_result();
      
          return $result;
      }
      

      【讨论】:

        【解决方案3】:

        得到答案!看来codeigniter的mysql驱动处理存储过程有bug。

        我通过更改将 config/database 文件中的驱动程序从 mysql 更改为 mysqli

        $db['default']['dbdriver'] = 'mysql';
        

        $db['default']['dbdriver'] = 'mysqli';
        

        发布我修改了 system/database/drivers/mysqli/mysqli_result.php 文件并添加了以下函数

        function next_result()
        {
          if (is_object($this->conn_id))
          {
              return mysqli_next_result($this->conn_id);
          }
        }
        

        并修改模型如下

        $db = $this->load->database('mailbox',TRUE);
        $qry_res = $db->query('Call circle_pending_p()');
        
        echo $db->_error_message();
        $res = $qry_res->result_array();
        
        $qry_res->next_result();
        $qry_res->free_result();
        
        if (count($res) > 0) {
              return $res;
        } else {
              return 0;
        }
        

        这解决了问题!

        【讨论】:

        • 如果使用mysqli,你可以调用mysqli_next_result($this->db->conn_id);在过程调用之后,从模型本身,而不必修改 mysqli 库
        【解决方案4】:

        试试:

        <?php
        while($dbms->more_results() && $dbms->next_result())
            {
                $result = $dbms->store_result();
        
                if(is_object($result)){ $result->free(); }
        
                unset($result);
            }
        ?>
        

        过程调用之后。 MySQLi 不能调用另一个过程,而有以前的结果。 在任何进一步的过程调用或查询执行之前,您应该为它们中的每一个使用free()

        来源:http://php.net/manual/en/mysqli.query.php

        【讨论】:

        • 这不起作用!它工作了一次,但再次收到错误消息! :(
        • 您应该在 ANY SQL procedure 调用并获得它的结果之后执行此操作。我这里没有t know how it should look while using you database wrapper. Still, you probably closed DB connection`:$db-&gt;close(); $db = $this-&gt;load-&gt;database('mailbox',TRUE);。我认为那里不需要。
        猜你喜欢
        • 2021-06-11
        • 1970-01-01
        • 2020-04-20
        • 1970-01-01
        • 2018-05-24
        • 2018-05-11
        • 2016-05-28
        • 2015-04-16
        相关资源
        最近更新 更多