Laravel_ORM集合中的chunk方法使用陷阱

问题代码如下:

DB::table('records')->where('status','=', 1)->chunk(50, function ($records) {
    if (empty($records)) {
        return;
    }
    //执行更新
    $records->each(function ($item, $key) {
        DB::table('records')->where('id','=', $item['id'])->update(['status' => 2]);
    });
});

问题分析

chunk方法解析的SQL形如:
SELECT * FROM records WHERE status = 1 OFFEST = {$offset} LIMIT {$limit}

以上代码解析的语句:

SELECT * FROM records WHERE status = 1 OFFEST = 0 LIMIT 50;
SELECT * FROM records WHERE status = 1 OFFEST = 50 LIMIT 50;
····
SELECT * FROM records WHERE status = 1 OFFEST = 50*n LIMIT 50;

如果查询条件一直在变化会导致OFFSET位移发生变化,导致错漏部分查询结果。

解决办法

$limit = 50;
while (true) {
    $records = DB::table('records')->where('status','=', 1)->limit(50)->get();
    //执行更新
    $records->each(function ($item, $key) {
          DB::table('records')->where('id','=', $item['id'])->update(['status' => 2]);
    });

    if(empty($records) || count($records) < $limit){
        break;
    }
}

总结

chunck 方法适用于记录查询场景,在更新记录是慎用

作者:T&D
Q Q:335749143
邮箱:tanda.arch#gmail.com(@替换#)
出处:http://www.cnblogs.com/one-villager/
* 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/one-villager/p/7567042.html