Laravel中的批量更新,具有每行的特定条件

时间:2017-10-26 14:16:55

标签: php mysql laravel bulkupdate

我正在使用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和run查询,这将非常耗时,因为我必须更新很多行。为了证明它,它将是这样的。

$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中完成,我该怎么办?

2 个答案:

答案 0 :(得分:0)

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

$_GET

功能:

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;
}

答案 1 :(得分:0)

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

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