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 方法适用于记录查询场景,在更新记录是慎用

posted @ 2017-09-21 10:01  oneVillager  阅读(1370)  评论(0编辑  收藏  举报
打赏

喜欢请打赏

扫描二维码打赏