【问题标题】:Bulk updating in Laravel with specific where condition for each row在 Laravel 中批量更新每行的特定 where 条件
【发布时间】:2018-02-14 13:57:15
【问题描述】:

我正在使用 Laravel 开发一个数据库驱动的网站。现在我在更新数据库时遇到问题。我想运行批量更新。平时我是这样跑的。

 $data = [
       [
         'col_1'=>$value1
       ],
       [
         'col_1'=>$value2
       ],
       [
         'col_1'=>$value3
       ],
       [
         'col_1'=>$value4
       ]
    ];
    MyTableObject::update($data)->where('col_2'=>$col_2_val);

正如您在上面的代码中看到的,where 子句只检查所有要更新的行的一个条件。但我想要的是每行或查询都需要不同的 where 子句条件。要对每一行使用 foreach 并运行查询,这将非常耗时,因为我必须更新很多行。为了演示它,它将是这样的。

$data = [
       [
         'col_1'=>$value1,
         'col_2'=>$where_value_1 // This is not the column to be updated. That is for where clause.
       ],
       [
         'col_1'=>$value2,
         'col_2'=>$where_value_2 // This is not the column to be updated. That is for where clause.
       ],
       [
         'col_1'=>$value3,
         'col_2'=>$where_value_3
       ],
       [
         'col_1'=>$value4,
         'col_2'=>$where_value_4
       ]
    ];
    MyTableObject::update($data)->where('where_col_name'=>'col_2');

我找到了this link,但答案并不清晰和完整。是否可以在 Laravel 中实现,我该怎么做?

【问题讨论】:

  • 为什么不在阵列上运行 foreach?应该不会很费时间...
  • 我必须更新数千条记录。所以我必须为每一行运行数千个查询。这很耗时。是的,我必须肯定使用 foreach,但我想知道如何在一个查询中更新?
  • 试试 MyTableObject::where('where_col_name'=>'col_2')->update($data);
  • 您的查询基本上是一组多个 where 子句,用于更改每个 where 条件的字段。所以,我认为它不能在单个查询中完成。您肯定需要考虑使用 for 循环,或者您的数据库模型可能不太正确。
  • 那为什么不将它作为 cron 运行,或者在需要更新时将其推送到队列中并处理它

标签: php mysql laravel bulkupdate


【解决方案1】:

如果我理解正确的话,col_1 是您希望在更新中使用的值,而 col_2 是您要查询的值。尝试以下(可能需要一些调整)

collect($data)->each(function(array $row) {
   MyTableObject::where('where_col_name', $row['col_2'])->update(['col_1' => $row['col_1']]);
});

【讨论】:

    【解决方案2】:

    这是我在 Laravel 项目中编写的批量更新功能。它的第一个参数是表名字符串,第二个是要更新行的键名字符串,主要是'id',第三个参数是格式的数据数组:

    array(
        array(
            'id' => 1,
            'col_1_name' => 'col_1_val',
            'col_2_name' => 'col_2_val',
            //.....
        ),
        array(
            'id' => 2,
            'col_1_name' => 'col_1_val',
            'col_2_name' => 'col_2_val',
            //.....
        ),
        //.....
    );
    

    功能:

    private function custom_batch_update(string $table_name = '', string $key = '', Array $update_arr = array()) {
    
        if(!$table_name || !$key || !$update_arr){
            return false;
        }
    
        $update_keys = array_keys($update_arr[0]);
        $update_keys_count = count($update_keys);
    
        for ($i = 0; $i < $update_keys_count; $i++) {
            $key_name = $update_keys[$i];
            if($key === $key_name){
                continue;
            }
            $when_{$key_name} = $key_name . ' = CASE';
        }
    
        $length = count($update_arr);
        $index = 0;
        $query_str = 'UPDATE ' . $table_name . ' SET ';
        $when_str = '';
        $where_str = ' WHERE ' . $key . ' IN(';
    
        while ($index < $length) {
            $when_str = " WHEN $key = '{$update_arr[$index][$key]}' THEN";
            $where_str .= "'{$update_arr[$index][$key]}',";
            for ($i = 0; $i < $update_keys_count; $i++) {
                $key_name = $update_keys[$i];
                if($key === $key_name){
                    continue;
                }
                $when_{$key_name} .= $when_str . " '{$update_arr[$index][$key_name]}'";
            }
            $index++;
        }
    
        for ($i = 0; $i < $update_keys_count; $i++) {
            $key_name = $update_keys[$i];
            if($key === $key_name){
                continue;
            }
            $when_{$key_name} .= ' ELSE ' . $key_name . ' END, ';
            $query_str .= $when_{$key_name};
        }
        $query_str = rtrim($query_str, ', ');
        $where_str = rtrim($where_str, ',') . ')';
        $query_str .= $where_str;
        $affected = DB::update($query_str);
    
        return $affected;
    }
    

    它将像这样生成并执行查询字符串:

    UPDATE table_name SET col_1_name = CASE 
    WHEN id = '1' THEN 'col_1_value' 
    WHEN id = '2' THEN 'col_1_value' 
    ELSE col_1_name END, 
    col_2_name = CASE 
    WHEN id = '1' THEN 'col_2_value' 
    WHEN id = '2' THEN 'col_2_value' 
    ELSE col_2_name END 
    WHERE id IN('1','2')
    

    【讨论】:

      猜你喜欢
      • 2011-11-17
      • 1970-01-01
      • 2011-01-08
      • 2014-10-30
      • 2020-10-04
      • 2014-11-25
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      相关资源
      最近更新 更多