如果我错了,请纠正我,但我认为 Eloquent 模型中没有大规模更新这样的东西。
有没有办法在不为每一行发出查询的情况下对数据库表进行大规模更新?
例如,是否有静态方法,例如
User::updateWhere(
array('age', '<', '18'),
array(
'under_18' => 1
[, ...]
)
);
(是的,这是一个愚蠢的例子,但你明白了......)
为什么没有实现这样的功能?如果出现这种情况,只有我会非常高兴吗?
我(开发人员)不想像这样实现它:
DB::table('users')->where('age', '<', '18')->update(array('under_18' => 1));
因为随着项目的发展,我们以后可能会要求程序员更改表名,他们无法搜索和替换表名!
有没有这样的静态方法来执行这个操作?如果没有,我们可以扩展 Illuminate\Database\Eloquent\Model
类来完成这样的事情吗?
也许这在几年前是不可能的,但在最近的 Laravel 版本中,你绝对可以做到:
User::where('age', '<', 18)->update(['under_18' => 1]);
值得注意的是,在调用 update
之前您需要 where 方法。
对于批量更新/插入功能,它被要求但 Taylor Otwell(Laravel 作者)建议用户应该使用 Query Builder。 https://github.com/laravel/framework/issues/1295
您的模型通常应该扩展 Illuminate\Database\Eloquent\Model。然后你自己访问实体,例如,如果你有这个:
<?php
Use Illuminate\Database\Eloquent\Model;
class User extends Model {
// table name defaults to "users" anyway, so this definition is only for
// demonstration on how you can set a custom one
protected $table = 'users';
// ... code omited ...
更新#2
您必须求助于查询生成器。为了解决表命名问题,您可以通过 getTable() 方法动态获取它。唯一的限制是您需要先初始化用户类,然后才能使用此功能。您的查询如下:
$userTable = (new User())->getTable();
DB::table($userTable)->where('age', '<', 18)->update(array('under_18' => 1));
这样你的表名就是用户模型中的控制器(如上例所示)。
更新#1
执行此操作的其他方法(在您的情况下效率不高)是:
$users = User::where('age', '<', 18)->get();
foreach ($users as $user) {
$user->field = value;
$user->save();
}
这样,表名就保存在 users 类中,您的开发人员不必担心它。
对@metamaker 答案的一点更正:
DB::beginTransaction();
// do all your updates here
foreach ($users as $user) {
$new_value = rand(1,10) // use your own criteria
DB::table('users')
->where('id', '=', $user->id)
->update(['status' => $new_value // update your field(s) here
]);
}
// when done commit
DB::commit();
现在您可以在一个数据库事务中进行 100 万次不同的更新
如果您需要无条件更新所有数据,请尝试以下代码
Model::query()->update(['column1' => 0, 'column2' => 'New']);
使用数据库事务批量更新多个实体。当你的更新函数完成时,事务将被提交,或者如果在两者之间发生异常,则回滚。
https://laravel.com/docs/5.4/database#database-transactions
例如,这就是我在单个批量更新中为文章重新生成具体化路径段 (https://communities.bmc.com/docs/DOC-9902) 的方式:
public function regenerateDescendantsSlugs(Model $parent, $old_parent_slug)
{
$children = $parent->where('full_slug', 'like', "%/$old_parent_slug/%")->get();
\DB::transaction(function () use ($children, $parent, $old_parent_slug) {
/** @var Model $child */
foreach ($children as $child) {
$new_full_slug = $this->regenerateSlug($parent, $child);
$new_full_title = $this->regenerateTitle($parent, $child);
\DB::table($parent->getTable())
->where('full_slug', '=', $child->full_slug)
->update([
'full_slug' => $new_full_slug,
'full_title' => $new_full_title,
]);
}
});
}
Laravel 6.*
我们可以按如下方式更新 query
上的海量数据:
Appointment::where('request_id' , $appointment_request->id)->where('user_id', Auth::user()->id)->where('status', '!=', 'Canceled')->where('id', '!=', $appointment->id)->update(['status' => 'Canceled', 'canceled_by' => Auth::user()->id]);
同一指令中批量查询和批量更新的另一个工作代码示例:
Coordinate::whereIn('id',$someCoordIdsArray)->where('status','<>',Order::$ROUTE_OPTIMIZED)
->update(['status'=>Order::$ROUTE_OPTIMIZED]);
laravel 5.8 你可以像这样完成批量更新:
User::where('id', 24)->update (dataAssociativeArray) ;