查询构造器 | 数据库 |《Laravel 8 中文文档 8.x》| Laravel China 社区


本站和网页 https://learnku.com/docs/laravel/8.x/queries/9401 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

查询构造器 | 数据库 |《Laravel 8 中文文档 8.x》| Laravel China 社区
Laravel
话题列表
社区 Wiki
优质外文
招聘求职
Laravel 实战教程
社区文档
登录
注册
Laravel 8 中文文档
展开或关闭
前言
发行说明
升级说明
贡献导引
入门指南
安装
配置信息
文件夹结构
Homestead
Valet
部署
核心架构
请求周期
服务容器
服务提供者
Facades
Contracts
基础功能
路由
中间件
CSRF 保护
控制器
请求
响应
视图
生成 URL
Session
表单验证
错误
日志
前端开发
Blade 模板
本地化
前端脚手架
编辑资源 Mix
安全相关
用户认证
用户授权
Email 认证
加密解密
哈希
重置密码
综合话题
Artisan 命令行
广播系统
缓存系统
集合
事件系统
文件存储
辅助函数
HTTP 客户端
邮件发送
消息通知
扩展包开发
队列
任务调度
数据库
快速入门
查询构造器
分页
数据库迁移
数据填充
Redis
Eloquent ORM
快速入门
模型关联
Eloquent 集合
修改器
API 资源
序列化
测试相关
快速入门
HTTP 测试
命令行测试
Dusk 浏览器测试
数据库测试
测试模拟器 Mocking
官方扩展包
Envoy 部署工具
Horizon 队列管理
Passport OAuth 认证
Sanctum 认证
Scout 全文搜索
Socialite 社会化登录
Telescope 调试工具
Laravel Sail
Laravel
首页
Laravel
Go
PHP
Vue.js
Python
Java
MySQL
Rust
LK
Elasticsearch
F2E 前端
Server
程序员
Database
DevTools
Computer Science
手机开发
AdonisJS
社区
Wiki
教程
Laravel 实战教程首页
《L01 Laravel 教程 - Web 开发实战入门》
《L02 Laravel 教程 - Web 开发实战进阶》
《L03 Laravel 教程 - 实战构架 API 服务器》
《L04 Laravel 教程 - 微信小程序从零到发布》
《L05 Laravel 教程 - 电商实战》
《L06 Laravel 教程 - 电商进阶》
《LX1 Laravel / PHP 扩展包视频教程》
《LX2 PHP 扩展包实战教程 - 从入门到发布》
《L07 Laravel 教程 - Laravel TDD 测试实战》
《LX3 Laravel 性能优化入门》
《LX4 Laravel / PHP 五分钟视频》
文档
社区文档首页
《Laravel 中文文档》
《Laravel 速查表》
《PHP 代码简洁之道》
《Laravel 编码技巧》
《Dcat Admin 中文文档》
《Laravel Nova 中文文档》
《Lumen 中文文档》
《Dingo API 中文文档》
《 Laravel 项目开发规范》
《构建 Laravel 开发环境》
登录
注册
微信登录
提交改进
查询构造器
8.x
9.x
8.5
8.x
7.x
6.x
5.8
5.7
5.6
5.5
5.4
5.3
5.2
5.1
Laravel 8 中文文档
未匹配的标注
本文档最新版为 9.x,旧版本可能放弃维护,推荐阅读最新版!
数据库:查询构造器
简介获取结果
分块结果聚合
查询原生表达式JoinsUnionsWhere 语句
参数分组Where Exists 语句子查询 Where 语句JSON Where 语句
Ordering, Grouping, Limit & Offset条件语句插入更新
更新 JSON自增自减
删除悲观锁调试
简介
Laravel 的数据库查询构造器为创建和运行数据库查询提供了一个方便的接口。它可以用于支持大部分数据库操作,并且在所有支持的数据库系统上统一运行。
Laravel 的查询构造器使用 PDO 参数绑定的形式,保护您的应用程序免受 SQL 注入攻击。因此不必清理因参数绑定而传入的字符串。
注意:PDO 不支持绑定列名。因此,不能让用户通过输入的方式,来指定查询语句从而引用的列名,包括 order by 字段等等。如果必须通过查询用户选择的方式引入的某些列,请始终根据允许列的白名单来校验列名。
获取结果
从一个数据表中获取所有行
你可以使用 DB facade 里的 table 方法来开始查询。table 方法为给定的表返回一个查询构造器实例,允许你在查询上链式调用更多的约束,最后使用 get 方法获取结果:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
/**
* 展示用户列表
* @return Response
*/
public function index()
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
get 方法返回一个包含 Illuminate\Support\Collection 实例的结果,其中每一条记录都是 PHP stdClass 对象的一个实例。你可以通过对象属性的方式来获取每个字段的值:
foreach ($users as $user) {
echo $user->name;
从数据表中获取单行或单列
如果你只需要从数据表中获取一行数据,你可以使用 first 方法。该方法返回一个 stdClass 对象:
$user = DB::table('users')->where('name', 'John')->first();
echo $user->name;
如果你甚至不需要整行数据,则可以使用 value 方法从记录中获取单个值。该方法将直接返回该字段的值:
$email = DB::table('users')->where('name', 'John')->value('email');
如果是通过 id 字段值获取一行数据,可以使用 find 方法:
$user = DB::table('users')->find(3);
获取一列的值
如果你想获取单列数据的集合,则可以使用 pluck 方法。在下面的例子中,我们将获取角色表中标题的集合:
$titles = DB::table('roles')->pluck('title');
foreach ($titles as $title) {
echo $title;
你还可以在返回的集合中指定字段的自定义键名:
$roles = DB::table('roles')->pluck('title', 'name');
foreach ($roles as $name => $title) {
echo $title;
分块结果
如果你需要处理上千上万条数据库记录,你可以考虑使用 chunk 方法。该方法每次获取结果集的一小块,并将其传递给 Closure 函数进行处理。该方法在 Artisan 命令 中处理大量查询数据的时候非常有用。例如,我们可以将全部 users 表数据切割成一次处理 100 条记录的一小块:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
//
});
你可以通过在 Closure 中返回 false 来终止继续获取分块结果:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
// Process the records...
return false;
});
如果要在分块结果中更新数据库记录,则块结果可能会和预计的返回结果不一致。 因此,在分块更新记录时,最好使用 chunkById 方法。 此方法将根据记录的主键自动对结果进行分页:
DB::table('users')->where('active', false)
->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('users')
->where('id', $user->id)
->update(['active' => true]);
});
注意:在分块的回调里面更新或删除记录时,对主键或外键的任何更改都可能影响分块查询。这可能会导致记录没有包含在分块结果中。
聚合
查询构造器还提供了各种聚合方法,比如count,max,min,avg,还有 sum。你可以在构造查询后调用任何方法:
$users = DB::table('users')->count();
$price = DB::table('orders')->max('price');
当然,你也可以将这些聚合方法与其他的查询语句相结合:
$price = DB::table('orders')
->where('finalized', 1)
->avg('price');
判断记录是否存在
除了通过 count 方法可以确定查询条件的结果是否存在之外,还可以使用 exists 和 doesntExist 方法:
return DB::table('orders')->where('finalized', 1)->exists();
return DB::table('orders')->where('finalized', 1)->doesntExist();
Selects
指定一个 Select 语句
当然你可能不是总是希望从数据库表中获取所有列。使用 select 方法,你可以自定义一个 select 查询语句来查询指定的字段:
$users = DB::table('users')->select('name', 'email as user_email')->get();
distinct 方法会强制让查询返回的结果不重复:
$users = DB::table('users')->distinct()->get();
如果你已经有了一个查询构造器实例,并且希望在现有的查询语句中加入一个字段,那么你可以使用 addSelect 方法:
$query = DB::table('users')->select('name');
$users = $query->addSelect('age')->get();
原生表达式
有时候你可能需要在查询中使用原生表达式。你可以使用 DB::raw 创建一个原生表达式:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
注意:原生表达式将会被当做字符串注入到查询中,因此你应该小心使用,避免创建 SQL 注入的漏洞。
原生方法
可以使用以下方法代替 DB::raw,将原生表达式插入查询的各个部分。
selectRaw
selectRaw 方法可以代替 select(DB::raw(...))。该方法的第二个参数是可选项,值是一个绑定参数的数组:
$orders = DB::table('orders')
->selectRaw('price * ? as price_with_tax', [1.0825])
->get();
whereRaw / orWhereRaw
whereRaw 和 orWhereRaw 方法将原生的 where注入到你的查询中。这两个方法的第二个参数还是可选项,值还是绑定参数的数组:
$orders = DB::table('orders')
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
->get();
havingRaw / orHavingRaw
havingRaw 和 orHavingRaw 方法可以用于将原生字符串设置为 having 语句的值:
$orders = DB::table('orders')
->select('department', DB::raw('SUM(price) as total_sales'))
->groupBy('department')
->havingRaw('SUM(price) > ?', [2500])
->get();
orderByRaw
orderByRaw 方法可用于将原生字符串设置为 order by 语句的值:
$orders = DB::table('orders')
->orderByRaw('updated_at - created_at DESC')
->get();
groupByRaw
groupByRaw 方法可以用于将原生字符串设置为 group by 语句的值:
$orders = DB::table('orders')
->select('city', 'state')
->groupByRaw('city, state')
->get();
Joins
Inner Join 语句
查询构造器也可以编写 join 方法。若要执行基本的「内链接」,你可以在查询构造器实例上使用 join 方法。传递给 join 方法的第一个参数是你需要连接的表的名称,而其他参数则使用指定连接的字段约束。你还可以在单个查询中连接多个数据表:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();
Left Join / Right Join 语句
如果你想使用 「左连接」或者 「右连接」代替「内连接」 ,可以使用 leftJoin 或者 rightJoin 方法。这两个方法与 join 方法用法相同:
$users = DB::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
$users = DB::table('users')
->rightJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
Cross Join 语句
使用 crossJoin 方法和你想要连接的表名做「交叉连接」。交叉连接在第一个表和被连接的表之间会生成笛卡尔积:
$sizes = DB::table('sizes')
->crossJoin('colors')
->get();
高级 Join 语句
你可以指定更高级的 join 语句。比如传递一个闭包作为 join 方法的第二个参数。此闭包接收一个 JoinClause 对象,从而指定 join 语句中指定的约束:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
})
->get();
如果你想要在连接上使用「where」 风格的语句,你可以在连接上使用 where 和 orWhere 方法。这些方法会将列和值进行比较,而不是列和列进行比较:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
子连接查询
你可以使用 joinSub,leftJoinSub 和 rightJoinSub 方法关联一个查询作为子查询。他们每一种方法都会接收三个参数:子查询,表别名和定义关联字段的闭包:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})->get();
Unions
查询构造器还提供了将两个查询「联合」的快捷方式。比如,你可以先创建一个查询,然后使用 union 方法将其和第二个查询进行联合:
$first = DB::table('users')
->whereNull('first_name');
$users = DB::table('users')
->whereNull('last_name')
->union($first)
->get();
技巧:你也可以使用 unionAll 方法,用法 union 方法是的一样。
Where Clauses
简单的 Where 语句
在构造 where 查询实例中,你可以使用 where 方法。调用 where 最基本的方式是需要传递三个参数:第一个参数是列名,第二个参数是任意一个数据库系统支持的运算符,第三个是该列要比较的值。
例如,下面是一个要验证 「votes」 字段的值等于 100 的查询:
$users = DB::table('users')->where('votes', '=', 100)->get();
为了方便,如果你只是简单比较列值和给定数值是否相等,可以将数值直接作为 where 方法的第二个参数:
$users = DB::table('users')->where('votes', 100)->get();
当然,你也可以使用其他的运算符来编写 where 子句:
$users = DB::table('users')
->where('votes', '>=', 100)
->get();
$users = DB::table('users')
->where('votes', '<>', 100)
->get();
$users = DB::table('users')
->where('name', 'like', 'T%')
->get();
你还可以传递条件数组到 where 函数中:
$users = DB::table('users')->where([
['status', '=', '1'],
['subscribed', '<>', '1'],
])->get();
Or 语句
你可以一起链式调用 where 约束,也可以在查询中添加 or 字句。orWhere 方法和 where 方法接收的参数一样:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere('name', 'John')
->get();
如果需要在括号内对 or 条件进行分组,将闭包作为 orWhere 方法的第一个参数也是可以的:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere(function($query) {
$query->where('name', 'Abigail')
->where('votes', '>', 50);
})
->get();
// SQL语句: select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
附加 Where 语句
whereBetween / orWhereBetween
whereBetween 方法验证字段值是否在给定的两个值之间:
$users = DB::table('users')
->whereBetween('votes', [1, 100])
->get();
whereNotBetween / orWhereNotBetween
whereNotBetween 方法用于验证字段值是否在给定的两个值之外:
$users = DB::table('users')
->whereNotBetween('votes', [1, 100])
->get();
whereIn / whereNotIn / orWhereIn / orWhereNotIn
whereIn 方法验证给定列的值是否包含在给定数组中:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
whereNotIn 方法验证给定列的值是否不存在给定的数组中:
$users = DB::table('users')
->whereNotIn('id', [1, 2, 3])
->get();
技巧:如果要在查询中添加大量整数绑定,则可以使用 whereIntegerInRaw 或 whereIntegerNotInRaw 方法来大大减少内存使用。
whereNull / whereNotNull / orWhereNull / orWhereNotNull
whereNull 方法验证指定的字段必须是 NULL:
$users = DB::table('users')
->whereNull('updated_at')
->get();
whereNotNull 方法验证指定的字段肯定不是 NULL:
$users = DB::table('users')
->whereNotNull('updated_at')
->get();
whereDate / whereMonth / whereDay / whereYear / whereTime
whereDate 方法用于比较字段值与给定的日期(年月日):
$users = DB::table('users')
->whereDate('created_at', '1989-01-09')
->get();
whereMonth 方法可用于将字段值与一年中的特定月份进行比较:
$users = DB::table('users')
->whereMonth('created_at', '01')
->get();
whereDay 方法可用于将字段值与一个月中的几号进行比较:
$users = DB::table('users')
->whereDay('created_at', '09')
->get();
whereYear 方法用于比较字段值与指定的年份:
$users = DB::table('users')
->whereYear('created_at', '1989')
->get();
whereTime 方法用于比较字段值与指定的时间(时分秒):
$users = DB::table('users')
->whereTime('created_at', '=', '11:20:45')
->get();
whereColumn / orWhereColumn
whereColumn 方法用于比较两个字段的值是否相等:
$users = DB::table('users')
->whereColumn('first_name', 'last_name')
->get();
你也可以传入一个比较运算符:
$users = DB::table('users')
->whereColumn('updated_at', '>', 'created_at')
->get();
你也可以给 whereColumn 传递一个数组,他们之间会使用 and 运算符连接:
$users = DB::table('users')
->whereColumn([
['first_name', '=', 'last_name'],
['updated_at', '>', 'created_at'],
])->get();
参数分组
有时候你需要创建更高级的 where 子句,例如「where exists」或者嵌套的参数分组。 Laravel 的查询构造器也能够处理这些。下面,让我们看一个在括号中进行分组约束的例子:
$users = DB::table('users')
->where('name', '=', 'John')
->where(function ($query) {
$query->where('votes', '>', 100)
->orWhere('title', '=', 'Admin');
})
->get();
你可以看到,通过使用 闭包 写入 where 的方法来创建一个查询构造器,用来约束一个分组。这个 闭包 接收一个查询实例,你可以使用这个实例来设置应该包含的约束。上面的例子将生成以下 SQL 语句:
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
技巧:你在调用 orWhere 的时候,应该始终使用分组,以避免应用全局作用出现意外。
Where Exists 语句
whereExists 方法允许你使用 where exists SQL 语句。whereExists 方法接收一个 闭包 作为参数,该闭包获取一个查询构建器实例,从而允许你定义放置在 「exists」 字句中的查询:
$users = DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
上述查询将产生如下的 SQL 语句:
select * from users
where exists (
select 1 from orders where orders.user_id = users.id
子查询 Where 语句
有时候,您可能需要构造一个 where 子句,将子查询的结果与给定值进行比较。您可以通过向 where 方法传递一个闭包和一个值来完成此操作。例如,下面的查询将检索最后一次「会员」购买记录是 「Pro」 类型的所有用户:
use App\Models\User;
$users = User::where(function ($query) {
$query->select('type')
->from('membership')
->whereColumn('user_id', 'users.id')
->orderByDesc('start_date')
->limit(1);
}, 'Pro')->get();
JSON Where 语句
Laravel 也支持查询 JSON 类型的字段(仅在对 JSON 类型支持的数据库上)。目前,本特性仅支持 MySQL 5.7、PostgreSQL、SQL Server 2016 以及 SQLite 3.9.0 (with the JSON1 extension)。使用 -> 操作符查询 JSON 数据:
$users = DB::table('users')
->where('options->language', 'en')
->get();
$users = DB::table('users')
->where('preferences->dining->meal', 'salad')
->get();
你也可以使用 whereJsonContains 来查询 JSON 数组 (在 SQLite 上不支持)
$users = DB::table('users')
->whereJsonContains('options->languages', 'en')
->get();
MySQL 和 PostgreSQL 的 whereJsonContains 可以支持多个值:
$users = DB::table('users')
->whereJsonContains('options->languages', ['en', 'de'])
->get();
你可以使用 whereJsonLength 来查询 JSON 数组的长度:
$users = DB::table('users')
->whereJsonLength('options->languages', 0)
->get();
$users = DB::table('users')
->whereJsonLength('options->languages', '>', 1)
->get();
Ordering, Grouping, Limit & Offset
orderBy
orderBy 方法允许你通过给定字段对结果集进行排序。 orderBy 的第一个参数应该是你希望排序的字段,第二个参数控制排序的方向,可以是 asc 或 desc:
$users = DB::table('users')
->orderBy('name', 'desc')
->get();
如果你需要使用多个字段进行排序,你可以多次引用 orderBy:
$users = DB::table('users')
->orderBy('name', 'desc')
->orderBy('email', 'asc')
->get();
latest / oldest
latest 和 oldest 方法让你以一种便捷的方式通过日期进行排序。它们默认使用 created_at 列作为排序依据。当然,你也可以传递自定义的列名:
$user = DB::table('users')
->latest()
->first();
inRandomOrder
inRandomOrder 方法被用来将结果进行随机排序。例如,你可以使用此方法随机找到一个用户:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
reorder
reorder 方法允许你删除已经存在的所有排序,如果你愿意,可以在之后附加一个新的排序。例如,你可以删除所有已存在的排序:
$query = DB::table('users')->orderBy('name');
$unorderedUsers = $query->reorder()->get();
删除所有已存在的排序并且附加新的排序,并且在方法上提供新的排序字段和顺序,用于重新排序:
$query = DB::table('users')->orderBy('name');
$usersOrderedByEmail = $query->reorder('email', 'desc')->get();
groupBy / having
groupBy 和 having 方法用于将结果分组。 having 方法的使用与 where 方法十分相似:
$users = DB::table('users')
->groupBy('account_id')
->having('account_id', '>', 100)
->get();
你可以向 groupBy 方法传递多个参数,来对结果使用多个字段进行分组:
$users = DB::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();
对于更高级的 having 语法,参见 havingRaw 方法。
skip / take
要限制结果的返回数量,或跳过指定数量的结果,你可以使用 skip 和 take 方法:
$users = DB::table('users')->skip(10)->take(5)->get();
或者你也可以使用 limit 和 offset 方法:
$users = DB::table('users')
->offset(10)
->limit(5)
->get();
条件语句
有时候你可能想要子句只适用于某个情况为真时才执行查询。例如你可能只想给定值在请求中存在的情况下才应用 where 语句。 你可以通过使用 when 方法来实现:
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
when 方法只有在第一个参数为 true 的时候才执行给的的闭包。如果第一个参数为 false ,那么这个闭包将不会被执行
你可以传递另一个闭包作为 when 方法的第三个参数。 该闭包会在第一个参数为 false 的情况下执行。为了说明如何使用这个特性,我们来配置一个查询的默认排序:
$sortBy = null;
$users = DB::table('users')
->when($sortBy, function ($query, $sortBy) {
return $query->orderBy($sortBy);
}, function ($query) {
return $query->orderBy('name');
})
->get();
插入
查询构造器还提供了 insert 方法用于插入记录到数据库中。 insert 方法接收数组形式的字段名和字段值进行插入操作:
DB::table('users')->insert(
['email' => 'john@example.com', 'votes' => 0]
);
你甚至可以将二维数组传递给 insert 方法,依次将多个记录插入到表中:
DB::table('users')->insert([
['email' => 'taylor@example.com', 'votes' => 0],
['email' => 'dayle@example.com', 'votes' => 0],
]);
insertOrIgnore 方法在将记录插入数据库时将忽略重复记录错误:
DB::table('users')->insertOrIgnore([
['id' => 1, 'email' => 'taylor@example.com'],
['id' => 2, 'email' => 'dayle@example.com'],
]);
自增 IDs
如果数据表有自增 ID ,使用 insertGetId 方法来插入记录可以返回 ID 值:
$id = DB::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
注意:当使用 PostgreSQL 时,insertGetId 方法将默认把 id 作为自动递增字段的名称。如果你要从其他「字段」来获取 ID ,则需要将字段名称作为第二个参数传递给 insertGetId 方法。
更新
当然, 除了插入记录到数据库中,查询构造器也可以通过 update 方法更新已有的记录。 update 方法和 insert 方法一样,接受包含要更新的字段及值的数组。你可以通过 where 子句对 update 查询进行约束:
$affected = DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
更新或新增
有时您可能希望更新数据库中的现有记录,或者如果不存在匹配记录则创建它。 在这种情况下,可以使用 updateOrInsert 方法。 updateOrInsert 方法接受两个参数:一个用于查找记录的条件数组,以及一个包含要更改记录的键值对数组。
updateOrInsert 方法将首先尝试使用第一个参数的键和值对来查找匹配的数据库记录。 如果记录存在,则使用第二个参数中的值去更新记录。 如果找不到记录,将插入一个新记录,新增的数据是两个数组的集合:
DB::table('users')
->updateOrInsert(
['email' => 'john@example.com', 'name' => 'John'],
['votes' => '2']
);
更新 JSON 字段
更新 JSON 字段时,你可以使用 -> 语法访问 JSON 对象中相应的值。注意,此操作只能支持 MySQL 5.7+ 和 PostgreSQL 9.5+ :
$affected = DB::table('users')
->where('id', 1)
->update(['options->enabled' => true]);
自增与自减
查询构造器还为给定字段的递增或递减提供了便捷的方式。此方法提供了一个比手动编写 update 语句更具表达力且更精练的接口。
这两种方法都至少接收一个参数:需要修改的列。可选的第二个参数用于控制列递增或递减的量:
DB::table('users')->increment('votes');
DB::table('users')->increment('votes', 5);
DB::table('users')->decrement('votes');
DB::table('users')->decrement('votes', 5);
你也可以在操作过程中指定要更新的其他字段:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
注意:当你使用模型中的 increment 和 decrement 方法时,会触发 updating 和 updated 模型事件。而在构造器中直接使用 increment 和 decrement,不会触发模型事件。
删除
查询构造器也可以使用 delete 方法从表中删除记录。 在使用 delete 前,可以添加 where 子句来约束 delete 语法:
DB::table('users')->delete();
DB::table('users')->where('votes', '>', 100)->delete();
您可以使用 truncate 方法来清空整个表,这将移除所有的数据并重置所有的自增 ID 为 0 :
DB::table('users')->truncate();
悲观锁
查询构造器也包含了一些能够帮助您在 select 语句中实现「悲观锁」的函数。要执行一个含有「共享锁」的语句,您可以在查询中使用 sharedLock 方法。共享锁可防止指定的数据列被篡改,直到事务被提交为止:
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
或者,您亦可使用 lockForUpdate 方法。使用「 update 」锁可以避免数据行被其他共享锁修改或选定:
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
调试
在绑定查询的时候,您可以使用 dd 或 dump 方法来输出查询绑定和 SQL。dd 方法将会显示调试信息并终止执行请求,而 dump 方法则会显示调试信息并允许请求继续执行:
DB::table('users')->where('votes', '>', 100)->dd();
DB::table('users')->where('votes', '>', 100)->dump();
本文章首发在 LearnKu.com 网站上。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
原文地址:https://learnku.com/docs/laravel/8.x/que...
译文地址:https://learnku.com/docs/laravel/8.x/que...
上一篇
下一篇
Markdown 文本
纠错改进
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
贡献者:11
推荐文章:
更多推荐...
翻译
Laravel 代码重构:使用 Services, Events, Jobs, Actions 来重构控制器方法
60
22
6个月前
博客
Git速查表
28
6个月前
博客
对线面试官:12个MySQL慢查询的原因分析
49
6个月前
翻译
Laravel 角色和权限:拦截器(Gates)和策略(Policies)解释
24
7个月前
分享
VUE3默认版本了,搞个音乐播放器项目熟悉一下
13
9个月前
翻译
如何在 Laravel 中找到最慢的查询
43
10个月前
讨论数量: 12
发起讨论
只看当前版本
kiyoma
4年前
多层次的条件判断如何用 when 来构造
个点赞 | 10 个回复 |
问答
| 课程版本 5.5
beyondxx3
4年前
如何跨数据库访问?
个点赞 | 3 个回复 |
问答
| 课程版本 5.5
shensu
3年前
Laravel 5.7 joinSub 子查询,如果有表前缀的话,别名怎么定义?
个点赞 | 0 个回复 |
问答
| 课程版本 5.7
miaotiao
3年前
关于 Laravel 文档的建议
个点赞 | 8 个回复 |
分享
| 课程版本 5.8
Janpun
2年前
Eloquent 如何查询具体时间
个点赞 | 4 个回复 |
问答
| 课程版本 5.5
wesen
3年前
having 方法与 where 的区别是什么?
个点赞 | 3 个回复 |
问答
| 课程版本 5.8
AmberLavigne
3年前
increment 和 decrement 添加条件使用的疑惑
个点赞 | 2 个回复 |
问答
| 课程版本 5.8
kiyoma
3年前
如果模型对应的表是个没有主键或者复合主键的表,就没法用 increment 或 decrement 了
个点赞 | 2 个回复 |
问答
| 课程版本 5.5
happyplay008
4年前
返回值
个点赞 | 2 个回复 |
问答
| 课程版本 5.5
miaotiao
3年前
数据库查询构造器笔记——持续更新
个点赞 | 0 个回复 |
分享
| 课程版本 5.8
zhizubaba
3年前
请问一下 JSON Where 语句 ->$[*] 这个 sql 怎么实现
个点赞 | 0 个回复 |
问答
| 课程版本 5.6
anuode
4年前
offset 自定义分页问题
个点赞 | 0 个回复 |
问答
| 课程版本 5.6
社区赞助商
成为赞助商
关于 LearnKu
LearnKu 是终身编程者的修道场
做最专业、严肃的技术论坛
LearnKu 诞生的故事
资源推荐
《社区使用指南》
《文档撰写指南》
《LearnKu 社区规范》
《提问的智慧》
服务提供商
其他信息
成为版主
所有测验
联系站长(反馈建议)
粤ICP备18099781号-6
粤公网安备 44030502004330号
违法和不良信息举报
由 Summer 设计和编码 ❤
请登录
提交
忘记密码?
or
注册
第三方账号登录
微信登录
GitHub 登录
内容举报
匿名举报,为防止滥用,仅管理员可见举报者。
我要举报该,理由是:
垃圾广告:恶意灌水、广告、推广等内容
无意义内容:测试、灌水、文不对题、消极内容、文章品质太差等
违规内容:色情、暴利、血腥、敏感信息等
不友善内容:人身攻击、挑衅辱骂、恶意行为
科学上网:翻墙、VPN、Shadowsocks,政策风险,会被关站!
不懂提问:提问太随意,需要再做一遍《提问的智慧》测验
随意提问:提问没有发布在社区问答分类下
排版混乱:没有合理使用 Markdown 编写文章,未使用代码高亮
内容结构混乱:逻辑不清晰,内容混乱,难以阅读
标题随意:标题党、标题不释义
尊重版权:分享付费课程、破解软件(付费),侵犯作者劳动成果
其他理由:请补充说明
举报
取消