Skip to content

查询构建器

介绍

数据库查询构建器提供了一个方便、流畅的接口来创建和运行数据库查询。它可以用于在应用程序中执行大多数数据库操作,并适用于所有支持的数据库系统。

lightbulb

Laravel 查询构建器在整个过程中使用 PDO 参数绑定,以保护您的应用程序免受 SQL 注入攻击。无需清理作为绑定传递的字符串。

选择

从表中检索所有行

php
$users = DB::table('users')->get();

foreach ($users as $user)
{
	var_dump($user->name);
}

从表中分块结果

php
DB::table('users')->chunk(100, function($users)
{
	foreach ($users as $user)
	{
		//
	}
});

您可以通过从 Closure 返回 false 来停止进一步的块处理:

php
DB::table('users')->chunk(100, function($users)
{
	//

	return false;
});

从表中检索单行

php
$user = DB::table('users')->where('name', 'John')->first();

var_dump($user->name);

从行中检索单列

php
$name = DB::table('users')->where('name', 'John')->pluck('name');

检索列值列表

php
$roles = DB::table('roles')->lists('title');

此方法将返回一个角色标题数组。您还可以为返回的数组指定自定义键列:

php
$roles = DB::table('roles')->lists('title', 'name');

指定选择子句

php
$users = DB::table('users')->select('name', 'email')->get();

$users = DB::table('users')->distinct()->get();

$users = DB::table('users')->select('name as user_name')->get();

向现有查询添加选择子句

php
$query = DB::table('users')->select('name');

$users = $query->addSelect('age')->get();

使用条件运算符

php
$users = DB::table('users')->where('votes', '>', 100)->get();

或语句

php
$users = DB::table('users')
                    ->where('votes', '>', 100)
                    ->orWhere('name', 'John')
                    ->get();

使用区间条件

php
$users = DB::table('users')
                    ->whereBetween('votes', [1, 100])->get();

使用非区间条件

php
$users = DB::table('users')
                    ->whereNotBetween('votes', [1, 100])->get();

使用数组的条件

php
$users = DB::table('users')
                    ->whereIn('id', [1, 2, 3])->get();

$users = DB::table('users')
                    ->whereNotIn('id', [1, 2, 3])->get();

使用空值条件查找未设置值的记录

php
$users = DB::table('users')
                    ->whereNull('updated_at')->get();

动态条件子句

您甚至可以使用“动态”条件语句,通过魔术方法流畅地构建条件语句:

php
$admin = DB::table('users')->whereId(1)->first();

$john = DB::table('users')
                    ->whereIdAndEmail(2, 'john@doe.com')
                    ->first();

$jane = DB::table('users')
                    ->whereNameOrAge('Jane', 22)
                    ->first();

排序、分组和条件

php
$users = DB::table('users')
                    ->orderBy('name', 'desc')
                    ->groupBy('count')
                    ->having('count', '>', 100)
                    ->get();

偏移和限制

php
$users = DB::table('users')->skip(10)->take(5)->get();

连接

查询构建器也可以用于编写连接语句。请查看以下示例:

基本连接语句

php
DB::table('users')
            ->join('contacts', 'users.id', '=', 'contacts.user_id')
            ->join('orders', 'users.id', '=', 'orders.user_id')
            ->select('users.id', 'contacts.phone', 'orders.price')
            ->get();

左连接语句

php
DB::table('users')
	    ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
	    ->get();

您还可以指定更高级的连接子句:

php
DB::table('users')
        ->join('contacts', function($join)
        {
        	$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
        })
        ->get();

如果您希望在连接上使用“条件”样式子句,可以在连接上使用 whereorWhere 方法。这些方法将比较列与值,而不是比较两个列:

php
DB::table('users')
        ->join('contacts', function($join)
        {
        	$join->on('users.id', '=', 'contacts.user_id')
        	     ->where('contacts.user_id', '>', 5);
        })
        ->get();

高级条件

参数分组

有时您可能需要创建更高级的条件子句,例如“存在”或嵌套参数分组。Laravel 查询构建器也可以处理这些:

php
DB::table('users')
            ->where('name', '=', 'John')
            ->orWhere(function($query)
            {
            	$query->where('votes', '>', 100)
            	      ->where('title', '<>', 'Admin');
            })
            ->get();

上述查询将生成以下 SQL:

sql
select * from users where name = 'John' or (votes > 100 and title <> 'Admin')

存在语句

php
DB::table('users')
            ->whereExists(function($query)
            {
            	$query->select(DB::raw(1))
            	      ->from('orders')
            	      ->whereRaw('orders.user_id = users.id');
            })
            ->get();

上述查询将生成以下 SQL:

sql
select * from users
where exists (
	select 1 from orders where orders.user_id = users.id
)

聚合

查询构建器还提供了多种聚合方法,例如 countmaxminavgsum

使用聚合方法

php
$users = DB::table('users')->count();

$price = DB::table('orders')->max('price');

$price = DB::table('orders')->min('price');

$price = DB::table('orders')->avg('price');

$total = DB::table('users')->sum('votes');

原始表达式

有时您可能需要在查询中使用原始表达式。这些表达式将作为字符串注入到查询中,因此请小心不要创建任何 SQL 注入点!要创建原始表达式,可以使用 DB::raw 方法:

使用原始表达式

php
$users = DB::table('users')
                     ->select(DB::raw('count(*) as user_count, status'))
                     ->where('status', '<>', 1)
                     ->groupBy('status')
                     ->get();

插入

向表中插入记录

php
DB::table('users')->insert(
	['email' => 'john@example.com', 'votes' => 0]
);

向具有自动递增 ID 的表中插入记录

如果表具有自动递增的 id,请使用 insertGetId 插入记录并检索 id:

php
$id = DB::table('users')->insertGetId(
	['email' => 'john@example.com', 'votes' => 0]
);
lightbulb

使用 PostgreSQL 时,insertGetId 方法期望自动递增列名为“id”。

向表中插入多条记录

php
DB::table('users')->insert([
	['email' => 'taylor@example.com', 'votes' => 0],
	['email' => 'dayle@example.com', 'votes' => 0]
]);

更新

更新表中的记录

php
DB::table('users')
            ->where('id', 1)
            ->update(['votes' => 1]);

增加或减少列的值

php
DB::table('users')->increment('votes');

DB::table('users')->increment('votes', 5);

DB::table('users')->decrement('votes');

DB::table('users')->decrement('votes', 5);

您还可以指定要更新的其他列:

php
DB::table('users')->increment('votes', 1, ['name' => 'John']);

删除

删除表中的记录

php
DB::table('users')->where('votes', '<', 100)->delete();

删除表中的所有记录

php
DB::table('users')->delete();

清空表

php
DB::table('users')->truncate();

联合

查询构建器还提供了一种快速的方法来将两个查询“联合”在一起:

php
$first = DB::table('users')->whereNull('first_name');

$users = DB::table('users')->whereNull('last_name')->union($first)->get();

unionAll 方法也可用,其方法签名与 union 相同。

悲观锁定

查询构建器包括一些函数来帮助您在 SELECT 语句上进行“悲观锁定”。

要使用“共享锁”运行 SELECT 语句,可以在查询上使用 sharedLock 方法:

php
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();

要在 SELECT 语句上“锁定以进行更新”,可以在查询上使用 lockForUpdate 方法:

php
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();