【问题标题】:Codeigniter - Batch Update with Multiple Where ConditionsCodeigniter - 具有多个 Where 条件的批量更新
【发布时间】:2011-11-17 13:44:47
【问题描述】:

对于初学者,关于 update_batch 的 Codeigniter 文档不存在。 kenjis 提供了一些文档并将其提交到存储库。希望他们尽快把它拉出来。

有谁知道如何在 Codeigniters update_batch 命令中添加多个 where 条件?

我的预期用途:

$where = array(
    'title',
    'name'
); 

$this->db->update_batch('mytable', $data, $where);

当我尝试此代码时,出现以下错误:

A Database Error Occurred
One or more rows submitted for batch updating is missing the specified index.

Filename: C:\wamp\www\wheel\system\database\DB_active_rec.php

Line Number: 1451

kenjis 更新批量文档:

$this->db->update_batch();

根据您提供的数据生成更新字符串,并运行查询。您可以将 arrayobject 传递给函数。下面是一个使用数组的例子:

$data = array(
    array(
        'title' => 'My title' ,
        'name' => 'My Name 2' ,
        'date' => 'My date 2'
    ),
    array(
        'title' => 'Another title' ,
        'name' => 'Another Name 2' ,
        'date' => 'Another date 2'
    )
);

$this->db->update_batch('mytable', $data, 'title');
// Produces: 
// UPDATE `mytable` SET `name` = CASE
// WHEN `title` = 'My title' THEN 'My Name 2'
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// ELSE `name` END,
// `date` = CASE 
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date` END
// WHERE `title` IN ('My title','Another title')

第一个参数将包含表名,第二个是一个关联数组,第三个参数是 where 键。

来源:

【问题讨论】:

    标签: codeigniter activerecord codeigniter-2


    【解决方案1】:

    您不能将多个 where 子句添加到 update_batch()。它只接受一个字符串作为 where 子句的第三个参数,所以我确信没有办法按照当前编写方法的方式执行此操作。

    来自source

    /**
     * Update_Batch
     *
     * Compiles an update string and runs the query
     *
     * @param   string  the table to retrieve the results from
     * @param   array   an associative array of update values
     * @param   string  the where key
     * @return  object
     */
    public function update_batch($table = '', $set = NULL, $index = NULL)
    

    【讨论】:

    • 太糟糕了,如果最后有第四个参数,那将是一个很好的补充。如果您直接使用 SQL,则可以在 UPDATE 查询的末尾添加一个“AND”。这似乎产生了预期的效果,例如:UPDATE mytable SET ... WHERE id IN(1,2,3) AND mycategory = 44
    【解决方案2】:

    我正在使用 codeigniter 3.1.5 并且遇到了同样的问题,但我解决了我的问题如下:

    $data = array(
        array(
            'title' => 'My title' ,
            'name' => 'My Name 2' ,
            'date' => 'My date 2'
        ),
        array(
            'title' => 'Another title' ,
            'name' => 'Another Name 2' ,
            'date' => 'Another date 2'
        )
    );
    
    $this->db->where('name','My Name 2');
    $this->db->update_batch('mytable', $data, 'title');
    

    生产它:

    // Produces:
    // UPDATE `mytable`
    // SET `name` = CASE
    //     WHEN `title` = 'Another title' THEN 'Another Name 2'
    //     WHEN `title` = 'My title' THEN 'My Name 2'
    //     ELSE `name`
    // END,
    //     `date` = CASE 
    //     WHEN `title` = 'My title' THEN 'My date 2'
    //     WHEN `title` = 'Another title' THEN 'Another date 2'
    //     ELSE `date`
    // END
    //     WHERE `title` IN ('My title','Another title')
    // AND `name` = 'My Name 2'
    

    更新

    我在尝试使用 update_batch 添加超过 100 条记录时遇到问题,例如:

    $data = [1=>a,2=>b ... 200=>zz];
    

    第一次调用(使用 WHERE):

    // Produces:
    // UPDATE `mytable`
    // SET `name` = CASE
    //    WHEN `title` = 'My title' THEN 'My Name 2'
    //    WHEN `title` = 'Another title' THEN 'Another Name 2'
    //    ELSE `name`
    // END,
    //  `date` = CASE 
    //    WHEN `title` = 'My title' THEN 'My date 2'
    //    WHEN `title` = 'Another title' THEN 'Another date 2'
    //    ELSE `date`
    // END
    //    WHERE `title` IN ('My title','Another title')
    //    AND `name` = 'My Name 2'
    

    第二次调用(没有 WHERE):

    // Produces:
    // UPDATE `mytable`
    // SET `name` = CASE
    //      WHEN `title` = 'My title' THEN 'My Name 2'
    //      WHEN `title` = 'Another title' THEN 'Another Name 2'
    //      ELSE `name`
    // END,
    //      `date` = CASE 
    //      WHEN `title` = 'My title' THEN 'My date 2'
    //      WHEN `title` = 'Another title' THEN 'Another date 2'
    //      ELSE `date`
    // END
    //      WHERE `title` IN ('My title','Another title')
    

    试试这个:

    $chunk1 = array_chunk($data,100);
    for($i=0;$i < count($chunk1);$i++) {
       $this->upload_model->update_data($chunk1[$i],'My Name 2');
    }
    

    型号:

    public function update_data($data='',$name=''){
       $this->db->where('name',$name);
       $this->db->update_batch('mytable', $data, 'title');
    }
    

    【讨论】:

    • 记住,我的第二个索引是静态值
    • 哇,伙计,你是个开箱即用的思想家。我永远不会这样想。谢谢
    • 如果你能想到第二个索引也是动态的方法!
    • 最好将update_batch的第三个参数包含在public function update_data的参数中
    • 不行,看看我的论坛帖子:forum.codeigniter.com/thread-68561.html
    【解决方案3】:

    update_batch 中的多个 where 条件被破坏,因为批处理循环中正在清除 WHERE 查询。

    这里是批量更新循环:

            for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size)
            {
                if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index)))
                {
                    $affected_rows += $this->affected_rows();
                }
    
                $this->qb_where = array();
            }
    

    请注意,传递的 WHERE 条件被 $this-&gt;qb_where = array(); 清除。

    在 CodeIgniter v3.1.10 中,违规行位于 DB_query_builder.php 中的 1940 上。这会产生一个非常意外的行为,其中 WHERE 条件适用于第一个处理的批次(默认 100),而后续批次则失败。

    有两种可能的解决方案:

    1. 使用update_batch的第4个batch_size参数,并传入100,000这样的大数,这样所有的查询都会在第一批中处理,不会清除WHERE条件。
    2. 更新违规行以恢复初始 WHERE 条件。

    解决方案 #2 的代码:

            // Save initial where conditions.
            $where_holder = $this->qb_where;
            // Batch this baby
            $affected_rows = 0;
            for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size)
            {
                if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index)))
                {
                    $affected_rows += $this->affected_rows();
                }
    
                // Restore intial where conditions.
                $this->qb_where = $where_holder;
            }
    

    希望这有帮助!

    【讨论】:

      【解决方案4】:
      Try this one also !
      Suppon you have import data through csv/excel
      then store all record in single array like:
      
      Array
      (
          [0] => Array
              (
                 
                  [price] => 100.00
                  [part_no] => PD001
                  [brand] => 44
                  [special_price] => 90.10
      
              )
      
          [1] => Array
              (
                  
                  [price] => 200.00
                  [part_no] => PD002
                  [special_price] => 150.00
                 
              )
      
      )
      
      Step 2:
      Call to model
      $model = new CatalogModel();
      $result = $model->batchUpdateData($final_array);
      
      
      function batchUpdateData($array = array()){
      
        $query = $this->db->table('product');
        $price = array();
        $part_no = array();
        $special = array();
        $brand = array();
      
        if (!empty($array)) {
         foreach ($array as $key => $value) {
          $price[] = $value['price'];
          $part_no[] = $value['part_no'];
          $special[] = $value['special_price'];
          $brand[] = $value['brand'];
      
        }
        
          $num = count($part_no);
          $sql ="UPDATE product SET "; 
         
         //  price colum update
           $sql .=" price = CASE ";
           for($i=0; $i < $num; $i++){
           $sql .=" WHEN  part_no = '".$part_no[$i]."' AND brand = '".$brand[$i]."'  THEN '".$price[$i]."' ";
      
         } 
          $sql .="ELSE price END ,";
          
          // special colum update
          $sql .=" special_price = CASE ";
          for($i=0; $i < $num; $i++){
          $sql .=" WHEN  part_no = '".$part_no[$i]."' AND brand = '".$brand[$i]."'  THEN '".$special[$i]."' ";
      
         } 
          $sql .="ELSE special_price END";
          
      
         $sql .=" WHERE part_no IN ('" . implode("','", $part_no) . "') ";
      
         return $this->db->query($sql);
      
       }
      
      }
      
      This will product query like:
      UPDATE `product` SET `price` = CASE WHEN `part_no` = 'PD001'  and `brand` = '44' THEN '100.00' WHEN `part_no` = 'PD002'  and `brand` = '44' THEN '200.00' ELSE `price` END 
      WHERE `part_no` IN('PD001','PD002');
      
      If this helpfull give a thumbs up
      

      【讨论】:

      • 请编辑您的答案,并提供有关代码功能的其他信息。见How to answer
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-19
      • 2015-09-25
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多