简体   繁体   English

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

[英]Bulk updating in Laravel with specific where condition for each row

I am developing a database-driven website using Laravel. 我正在使用Laravel开发数据库驱动的网站。 Now I am having a problem with updating database. 现在我在更新数据库时遇到问题。 I want to run bulk update. 我要运行批量更新。 Normally I run like this. 通常我会这样跑。

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

As you can see in the above code, where clause is checking for only one condition for all rows that are to be updated. 如您在上面的代码中所看到的,where子句仅检查要更新的所有行的一个条件。 But what I want is that I want the different where clause condition for each row or query. 但是我想要的是我想要每行或查询都使用不同的where子句条件。 To use foreach and run query for each row, it will be time-consuming because I have to update a lot of rows. 要对每行使用foreach并运行查询,这将非常耗时,因为我必须更新很多行。 To demonstrate it, it will be something like this. 为了证明这一点,将是这样的。

$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');

I found this link , but the answers are not clear and complete. 我找到了此链接 ,但是答案并不清晰完整。 Is it possible to do it in Laravel, and how can I do it? 在Laravel中可以做到吗,我该怎么办?

Here is the batch update function which I wrote to use in my Laravel projects. 这是我编写的在Laravel项目中使用的批处理更新功能。 Its first parameter is the table name string, second is the key name string on which you want to update the row or rows and mostly it will be the 'id', the third parameter is the data array in the format: 它的第一个参数是表名称字符串,第二个是您要在其上更新行的键名称字符串,并且大多数情况下将是“ 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',
        //.....
    ),
    //.....
);

Function: 功能:

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

It will produce and execute the query string like this: 它将产生并执行如下查询字符串:

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')

If I'm understanding this correctly, col_1 is the value you wish to use in update and col_2 is the value you're querying against. 如果我正确理解这一点,则col_1是您希望在更新中使用的值,而col_2是您要查询的值。 Try the following (may need some adjustments) 请尝试以下操作(可能需要进行一些调整)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM