thinkphp的数据库操作(上)

如果想了解更多相关知识,可以前往我的个人博客看看:eyes++的个人空间

一:连接数据库与模型初探

ThinkPHP 采用内置抽象层将不同的数据库操作进行封装处理,数据抽象层基于 PDO 模式,无须针对不同的数据库编写相应的代码。使用数据库的第一步,就是连接数据库,在根目录的 config 下的 database.php 可以设置数据库连接信息,大部分系统已经给了默认值,你只需要修改和填写需要的值即可。
在这里插入图片描述其中default配置用于设置默认使用的数据库连接配置。connections配置具体的数据库连接信息,default配置参数定义的连接配置必须要存在。

type数据库
mysqlMySQL
sqliteSqLite
pgsqlPostgreSQL
sqlsrvSqlServer
mongoMongoDb
oracleOracle

下面是默认支持的数据库连接信息:

参数名描述默认值
type数据库类型
hostname数据库地址127.0.0.1
database数据库名称
username数据库用户名
password数据库密码
hostport数据库端口号
dsn数据库连接dsn信息
params数据库连接参数
charset数据库编码utf8
prefix数据库的表前缀
deploy数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)0
rw_separate数据库读写是否分离 主从式有效false
master_num读写分离后 主服务器数量1
slave_no指定从服务器序号
fields_strict是否严格检查字段是否存在true
fields_cache是否开启字段缓存false
schema_cache_path字段缓存目录
trigger_sql是否开启SQL监听true
auto_timestamp自动写入时间戳字段false
query指定查询对象think\db\Query
我们还可以调用Db::connect方法动态配置数据库连接信息,例如:
\think\facade\Db::connect('demo')
	->table('user')
    ->find();

connect方法必须在查询的最开始调用,而且必须紧跟着调用查询方法,否则可能会导致部分查询失效或者依然使用默认的数据库连接。且动态连接数据库的connect方法仅对当次查询有效。这种方式的动态连接和切换数据库比较方便,经常用于多数据库连接的应用需求。

对于本地测试,会优先采用.env 的配置信息,可以通过删除改变.env 的配置,或删除.env 来验证 database 的执行优先级,操作中我们和 database 配置对应上即可:
在这里插入图片描述
现在来测试有没有成功连接:

在这里插入图片描述

二:查询构造器(基础)

在学习查询之前可以先了解一下一个新方法:Db::getLastSql(),该方法可以返回最近一条SQL查询的原生语句。我在这里的演示是使用了我的myemployees库内容如下:
在这里插入图片描述在这里插入图片描述

1) 查询数据

查询单个数据

查询单个数据一般使用find方法。如果没有任何的查询条件,并且也没有调用order方法的话 ,find查询不会返回任何结果。

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result = json(Db::table('employees')->where('employee_id', 100)->find());
        return Db::getLastSql() . '<br>' . $result;
    }
}

在这里插入图片描述find方法查询结果不存在,返回 null,否则返回结果数组,如果希望查询数据不存在的时候返回空数组,可以如下修改:

$result = Db::table('employees')->where('employee_id', 99)->findOrEmpty();

如果希望在没有找到数据后抛出异常可以如下使用,如果没有查找到数据,则会抛出一个think\db\exception\DataNotFoundException异常。

$result = Db::table('employees')->where('employee_id', 99)->findOrFail();

查询数据集

查询多个数据(数据集)使用select方法:
在这里插入图片描述
select 方法查询结果是一个数据集对象,如果需要转换为数组可以如下使用,但一般DB操作返回是默认是数组,这种情况下调用toArray()会报错,别问我是怎么知道的。。。。

$result = Db::table('employees')->where('employee_id', 102)->select()->toArray();

如果希望在没有查找到数据后抛出异常可以如下使用,如果没有查找到数据,同样也会抛出一个think\db\exception\DataNotFoundException异常

$result = Db::table('employees')->where('employee_id', 102)->select()->selectOrFail();

如果设置了数据表前缀参数的话,可以使用name替代table,如果表名为"tp_user",然后在数据库设置那里添加了表前缀"tp_",那么查询时可以用name('user')替代table('tp_user')。如果你的数据表没有设置表前缀的话,那么name和table方法效果一致。

值和列查询

查询某个字段的值可以用value(),如果不存在则返回null,如果有多个结果则只返回第一个。
在这里插入图片描述查询某一列的值可以用column(),第一个参数是返回的值,第二个参数的值作为索引。
在这里插入图片描述

数据分批处理

如果处理的数据量巨大,成百上千那种,一次性读取有可能会导致内存开销过大,为了避免内存处理太多数据出错,可以使用 chunk()方法分批处理数据,该方法一次获取结果集的一小块,然后填充每一小块数据到要处理的闭包,该方法在编写处理大量数据库记录的时候非常有用。比如,我们可以全部员工表数据进行分批处理,每次处理 3 个员工记录,先展示chunk分批次处理的特性。

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        // function传入的$data代表所有数据
        $result = Db::table('employees')->chunk(3, function ($data){
            foreach ($data as $data) {
                dump($data);
            }
            echo 1;
        });
    }
}

在这里插入图片描述如果要给员工计算年薪,那就是 月薪*12*(1+奖金率),那样就可以通过如下方法计算了:

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        // function传入的$data代表所有数据
        $result = Db::table('employees')->chunk(3, function ($data){
            foreach ($data as $data) {
                if (isset($data['commission_pct'])) {
                    echo $data['employee_id'] . ' ' . (12*$data['salary']*(1+$data['commission_pct'])) . "<br>";
                } else {
                    echo $data['employee_id'] . ' ' . (12*$data['salary']) . "<br>";
                }
            }
            echo 1 . "<br>";
        });
    }
}

在这里插入图片描述chunk方法的处理默认是根据主键查询,支持指定字段,并且支持指定处理数据的顺序。

Db::table('think_user')->chunk(100, function($users) {
    // 处理结果集...
    return false;
},'create_time', 'desc');

游标查询

可以利用游标查询功能,可以大幅度减少海量数据的内存开销,它利用了 PHP 生 成器特性。每次查询只读一行,然后再读取时,自动定位到下一行继续读取,cursor方法返回的是一个生成器对象。

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result = Db::table('employees')->cursor();
        foreach ($result as $e){
            echo $e['last_name'] . "<br>";
        };
    }
}

在这里插入图片描述

2) 添加数据

单数据新增

单数据新增一般使用insert()方法插入,如果新增成功会返回一个1,没有指定的列的值默认为null。

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $data = [
            'employee_id'   =>  '99',
            'first_name'    =>  'eyes',
            'last_name'     =>  '++'
        ];
        return Db::table('employees')->insert($data);
    }
}

在这里插入图片描述如果你添加一个不存在的字段数据,会抛出一个异常 Exception,如果想强行新增抛弃不存在的字段数据,则使用 strick(false)方法,忽略异常:

return Db::table('employees')->strict(false)->insert($data);

我采用的数据库是 mysql,可以支持 replace 写入,insert 和 replace 写入的区别,前者遇到表中存在主键相同则报错,后者则修改。另外,使用 insertGetId()方法,可以在新增成功后返回当前数据 ID

批量数据新增

使用 insertAll()方法,可以添加二维数组批量新增数据,但要保持数组结构一致,成功则返回增加的行数

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $data =[
            [
                'employee_id'   =>  '98',
                'first_name'    =>  '虚哥',
                'last_name'     =>  'xx'
            ],
            [
                'employee_id'   =>  '97',
                'first_name'    =>  '鸡哥',
                'last_name'     =>  'jj'
            ]
        ];
        return Db::table('employees')->insertAll($data);
    }
}

在这里插入图片描述
如果是mysql数据库则可以使用replay()批量添加或修改:

return Db::table('employees')->replay()->insertAll($data);

如果批量插入的数据比较多,可以指定分批插入,使用limit方法指定每次插入的数量限制:

//分批次写入,每次最多100条数据
Db::table('employees')
  ->replay()
  ->limit(100)
  ->insertAll($data);

save()新增

save()方法是一个通用方法,可以自行判断是新增还是修改(更新)数据,判断的依据是是否存在主键,不存在即新增。用法如insert,此处略。

3) 更新数据

更新数据可以使用save()方法或者update()方法,如果修改数据包括了主键信息,则可以省略where条件

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $data =[
            'first_name'    =>  '东哥',
            'last_name'     =>  'hh'
        ];
        return Db::table('employees')
            ->where('employee_id', 97)
            ->save($data);
//        支持使用data方法传入要更新的数据,如果update方法和data方法同时传入更新数据,则以update方法为准。
//        return Db::table('employees')
//        ->where('employee_id', 97)
//        ->data($data)
//        ->save();
    }
}

在这里插入图片描述如果要更新的数据需要使用SQL函数或者其它字段,可以使用下面的方式:

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        return Db::table('employees')
            ->where('employee_id', 99)
            ->exp('first_name', 'UPPER(first_name)')
            ->update();
    }
}

在这里插入图片描述
可以使用inc/dec方法自增或自减一个字段的值( 如不加第二个参数,默认步长为1)。

// score 字段加 1
Db::table('employees')
    ->where('employee_id', 1)
    ->inc('salary')
    ->update();

// score 字段加 5
Db::table('employees')
    ->where('employee_id', 1)
    ->inc('salary', 5)
    ->update();

// score 字段减 1
Db::table('employees')
    ->where('employee_id', 1)
    ->dec('salary')
    ->update();

// score 字段减 5
Db::table('employees')
    ->where('employee_id', 1)
    ->dec('salary', 5)
    ->update();

4) 删除数据

  • 极简删除可以根据主键直接删除,删除成功返回影响行数,否则 0;
    Db::table('employees')->delete(100);
  • 根据主键,还可以删除多条记录;
    Db::table('employees')->delete([97,98,99]);
  • 正常情况下,通过 where()方法来删除;
    Db::table('employees')->where('id', 100)->delete();
  • 通过 true 参数删除数据表所有数据
    Db::table('employees')->delete(true);

一般情况下,业务数据不建议真实删除数据,系统提供了软删除机制(模型中使用软删除更为方便),useSoftDelete方法表示使用软删除,并且指定软删除字段为delete_time,写入数据为当前的时间戳。。

// 软删除数据 使用delete_time字段标记删除
Db::table('employees')
	->where('id', 100)
	->useSoftDelete('delete_time',time())
    ->delete();

在这里插入图片描述

5) 查询表达式

查询表达式支持大部分的SQL查询语法,也是ThinkPHP查询语言的精髓,查询表达式的使用格式:where('字段名','查询表达式','查询条件')。除了where方法外,还可以支持whereOr,用法是一样的。为了更加方便查询,大多数的查询表达式都提供了快捷查询方法。

表达式含义快捷查询方法
=等于
<>不等于
>大于
>=大于等于
<小于
<=小于等于
[NOT] LIKE模糊查询whereLike/whereNotLike
[NOT] BETWEEN(不在)区间查询whereBetween/whereNotBetween
[NOT] IN(不在)IN 查询whereIn/whereNotIn
[NOT] NULL查询字段是否(不)是NULLwhereNull/whereNotNull
[NOT] EXISTSEXISTS查询whereExists/whereNotExists
[NOT] REGEXP正则(不)匹配查询(仅支持Mysql)
[NOT] BETWEEN TIME时间区间比较whereBetweenTime
> TIME大于某个时间whereTime
< TIME小于某个时间whereTime
>= TIME大于等于某个时间whereTime
<= TIME小于等于某个时间whereTime
EXP表达式查询,支持SQL语法whereExp
find in setFIND_IN_SET查询whereFindInSet

比较查询

  • 查询表达式支持大部分常用的 SQL 语句,语法格式如下:
    where('字段名','查询表达式','查询条件');
  • 在查询数据进行筛选时,我们采用 where()方法,比如 id=80;
    Db::name('user')->where('id', 80)->find();
    Db::name('user')->where('id','=',80)->find();
  • 使用<>、>、<、>=、<=可以筛选出各种符合比较值的数据列表; Db::name('user')->where('id','>',80)->select();

区间查询

  • 使用 like 表达式进行模糊查询;
    Db::name('user')->where('email','like','xiao%')->select();
  • like 表达式还可以支持数组传递进行模糊查询;
    Db::name('user')->where('email','like',['xiao%','wu%'], 'or')->select();
    SELECT * FROM tp_user WHERE (email LIKE xiao% OR email LIKE 'wu%')
  • like 表达式具有两个快捷方式 whereLike()和 whereNoLike(); Db::name('user')->whereLike('email','xiao%')->select();
    Db::name('user')->whereNotLike('email','xiao%')->select();
  • between 表达式具有两个快捷方式 whereBetween()和 whereNotBetween(); Db::name('user')->where('id','between','19,25')->select();
    Db::name('user')->where('id','between',[19, 25])->select();
    Db::name('user')->whereBetween('id','19,25')->select(); Db::name('user')->whereNotBetween('id','19,25')->select();
  • in 表达式具有两个快捷方式 whereIn()和 whereNotIn();
    Db::name('user')->where('id','in', '19,21,29')->select();
    Db::name('user')->where('id','in', [19, 21, 29])->select();
    Db::name('user')->whereIn('id','19,21,29')->select();
    Db::name('user')->whereNotIn('id','19,21,29')->select();
  • null 表达式具有两个快捷方式 whereNull()和 whereNotNull(); Db::name('user')->where('uid','null')->select();
    Db::name('user')->where('uid','not null')->select();
    Db::name('user')->whereNull('uid')->select();
    Db::name('user')->whereNotNull('uid')->select();

EXP查询

EXP表达式支持更复杂的查询:

Db::name('user')->where('id','in','1,3,8')->select();

可以改成:

Db::name('user')->where('id','exp',' IN (1,3,8) ')->select();

exp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称。因此推荐使用whereExp方法查询。

Db::name('user')->whereExp('id', 'IN (1,3,8) ')->select();

三:查询构造器(链式)

1).查询规则

  1. 前面课程中我们通过指向符号“->”多次连续调用方法称为:链式查询
  2. 当 Db::name(‘user’)时,返回查询对象(Query),即可连缀数据库对应的方法
  3. 而每次执行一个数据库查询方法时,比如 where(),还将返回查询对象(Query)
  4. 只要还是数据库对象,那么就可以一直使用指向符号进行链式查询
  5. 再利用 find()、select()等方法返回数组(Array)或数据集对象(Colletion)
  6. 而 find()和 select()是结果查询方法(放在最后),并不是链式查询方法
    Db::name('user')->where('id', 27)->order('id', 'desc')->find()
  7. 除了查询方法可以使用链式连贯操作,CURD 操作也可以使用(后续课程研究)

2).更多查询

  1. 如果多次使用数据库查询,那么每次静态创建都会生成一个实例,造成浪费;
  2. 我们可以把对象实例保存下来,再进行反复调用即可;
    $userQuery = Db::name('user');
    $dataFind = $userQuery->where('id', 27)->find();
    $dataSelect = $userQuery->select();
  3. 当同一个对象实例第二次查询后,会保留第一次查询的值;
    $data1 = $userQuery->order('id', 'desc')->select();
    $data2 = $userQuery->select();
    return Db::getLastSql();
    SELECT * FROM tp_user ORDER BY id DESC
  4. 使用 removeOption()方法,可以清理掉上一次查询保留的值; $userQuery->removeOption('where')->select();

3). 链式查询方法

where

  • 表达式查询,即where()方法的基础查询方式
 $result=Db::table('employees')->where('salary', '<', '10000')->select();
  • 关联数组查询,通过键值对来数组键值对匹配的查询方式
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where([
                      'job_id'     =>      'IT_PROG',
                      'salary'     =>       6000
                  ])
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 索引数组查询,通过数组里的数组拼装方式来查询
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where([
                      ['employee_id', '<', 110],
                      ['salary', '<', 10000]
                  ])
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 将复杂的数组组装后,通过变量传递,将增加可读性
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $map[] = ['employee_id', '<', 110];
        $map[] = ['salary', 'in', [6000, 4200, 24000]];
        $result=Db::table('employees')
                  ->where($map)
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 字符串形式传递,简单粗暴的查询方式,whereRaw()支持复杂字符串格式,也支持SQL预处理模式
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->whereRaw("employee_id<110 AND salary IN (24000, 6000, 4200)")
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

field

  • 使用 field()方法,可以指定要查询的字段
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where('employee_id', '<', 105)
                  ->field('employee_id, first_name, salary')
//                  ->field(['employee_id', 'first_name', 'salary']) 或者这种数组形式
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 使用 field()方法,给指定的字段设置别名
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where('employee_id', '<', 105)
                  ->field('employee_id as id, first_name as name, salary as 薪水')
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 在 fieldRaw()方法里,可以直接给字段设置 MySQL 函数
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where('employee_id', '<', 105)
                  ->field('job_id, LENGTH(job_id)')
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 使用 field(true)的布尔参数,可以显式的查询获取所有字段,而不是*
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
                  ->where('employee_id', '<', 105)
                  ->field(true)
                  ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 使用 withoutField()方法中字段排除,可以屏蔽掉想要不显示的字段
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->where('employee_id', '<', 105)
            ->withoutField('email, phone_number')
            ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 使用 field()方法在新增时,验证字段的合法性
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->where('employee_id', '<', 105)
            ->field('employee_id, first_name, last_name')
            ->insert([
                'first_name'       =>      '济钢',
                'last_name'        =>       'aa'
            ]);
        return json($result);
    }
}

在这里插入图片描述

alias

使用 alias()方法,给数据库起一个别名:
在这里插入图片描述

limit

  • 使用 limit()方法,限制获取输出数据的个数
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name')
            ->limit(5)
            ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 分页模式,即传递两个参数,比如从第 3 条开始显示 5 条 limit(2,5)
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name')
            ->limit(2, 5)
            ->select();
        return json($result);
    }
}

在这里插入图片描述

page

page()分页方法,优化了 limit()方法,无须计算分页条数

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name')
            ->page(2, 5)  // 每页显示五条,第二页
            ->select();
        return json($result);
    }
}

在这里插入图片描述

order

  • 使用 order()方法,可以指定排序方式,没有指定第二参数,默认 asc
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name, salary')
            ->order('salary', 'desc')
            ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 支持数组的方式,对多个字段进行排序
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name, salary')
            // 按工资升序,工资相同则按员工编号降序
            ->order([
                'salary'        =>       'asc',
                'employee_id'   =>       'desc'
            ])
            ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 使用 orderRaw()方法,支持排序的时候指定 MySQL 函数
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('employee_id, last_name, salary')
            ->orderRaw('length(first_name) DESC')
            ->select();
        return Db::getLastSQL();
    }
}

在这里插入图片描述

group

  • 使用 group()方法,给性别不同的人进行 price 字段的总和统计
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('job_id, SUM(salary)')
            ->group('job_id')
            ->select();
        return json($result);
    }
}

在这里插入图片描述

  • 也可以进行多字段分组统计
<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('job_id, manager_id, SUM(salary)')
            ->group('job_id, manager_id')
            ->select();
        return json($result);
    }
}

在这里插入图片描述

having

使用 group()分组之后,再使用 having()进行筛选

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $result=Db::table('employees')
            ->field('job_id, manager_id, SUM(salary)')
            ->group('job_id, manager_id')
            ->having('SUM(salary)>10000')
            ->select();
        return json($result);
    }
}

在这里插入图片描述

四:查询构造器(进阶)

1) 聚合查询

在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等,ThinkPHP为这些统计操作提供了一系列的内置方法,包括以下部分:

方法说明
count统计数量,参数是要统计的字段名(可选)
max获取最大值,参数是要统计的字段名(必须)
min获取最小值,参数是要统计的字段名(必须)
avg获取平均值,参数是要统计的字段名(必须)
sum获取总分,参数是要统计的字段名(必须)
  1. 使用 count()方法,可以求出所查询数据的数量
    Db::name('user')->count();
  2. count()可设置指定 id,比如有空值(Null)的 uid,不会计算数量;
    Db::name('user')->count('uid');
  3. 使用 max()方法,求出所查询数据字段的最大值;
    Db::name('user')->max('price');
  4. 如果 max()方法,求出的值不是数值,则通过第二参数强制转换;
    Db::name('user')->max('price', false);
  5. 使用 min()方法,求出所查询数据字段的最小值,也可以强制转换;
    Db::name('user')->min('price');
  6. 使用 avg()方法,求出所查询数据字段的平均值;
    Db::name('user')->avg('price');
  7. 使用 sum()方法,求出所查询数据字段的总和;
    Db::name('user')->sum('price');

2) 分页查询

3) 时间查询

传统方式

  • 可以使用>、<、>=、<=来筛选匹配时间的数据;
    Db::name('user')->where('create_time', '>', '2018-1-1')->select();
  • 可以使用 between 关键字来设置时间的区间
    Db::name('user')->where('create_time', 'between', ['2018-1-1', '2019-12-31'])->select();
    Db::name('user')->where('create_time', 'not between', ['2018-1-1', '2019-12-31'])->select();

快捷方式

  • 时间查询的快捷方法为 whereTime(),直接使用>、<、>=、<=; Db::name('user')->whereTime('create_time', '>', '2018-1-1')->select();
  • 快捷方式也可以使用 between 和 not between;
    Db::name('user')->whereBetween('create_time', ['2018-1-1', '2019-12-31'])->select();
  • 还有一种快捷方式为:whereBetweenTime()和 whereNotBetweenTime(); Db::name('user')->whereBetweenTime('create_time', '2018-1-1', '2019-12-31')->select();
  • 默认的大于>,可以省略;
    Db::name('user')->whereTime('create_time', '2018-1-1')->select();

固定查询

  • 使用 whereYear 查询今年的数据、去年的数据和某一年的数据
    Db::name('user')->whereYear('create_time')->select();
    Db::name('user')->whereYear('create_time', 'last year')->select();
    Db::name('user')->whereYear('create_time', '2016')->select();
  • 使用 whereMonth 查询当月的数据、上月的数据和某一个月的数据
    Db::name('user')->whereMonth('create_time')->select();
    Db::name('user')->whereMonth('create_time', 'last month')->select();
    Db::name('user')->whereMonth('create_time', '2016-6')->select();
  • 使用 whereDay 查询今天的数据、昨天的数据和某一个天的数据
    Db::name('user')->whereDay('create_time')->select();
    Db::name('user')->whereDay('create_time', 'last day')->select();
    Db::name('user')->whereDay('create_time', '2016-6-27')->select();

其它查询

  • 查询指定时间的数据,比如两小时内的
    Db::name('user')->whereTime('create_time', '-2 hours')->select();
  • 查询两个时间字段时间有效期的数据,比如会员开始到结束的期间
    Db::name('user')->whereBetweenTimeField('start_time', 'end_time')->select();

4) 高级查询

快捷查询

快捷查询方式是一种多字段相同查询条件的简化写法,可以进一步简化查询条件的写法,在多个字段之间用|分割表示OR查询,用&分割表示AND查询,可以实现下面的查询,例如:

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        Db::table('employees')
            ->where('first_name|last_name', 'like', '%a%')
            ->where('employee_id&manager_id', '>', 103)
            ->select();
        return Db::getLastSql();
    }
}

在这里插入图片描述在这里插入图片描述

闭包查询

<?php
namespace app\controller;
use think\facade\Db;

class DbTest
{
    public function index()
    {
        $jobId='IT_PROG';
        $salary=11000;

        $res=Db::table('employees')->where(function ($query) use($jobId, $salary) {
            $query->where('job_id', $jobId)
                  ->whereOr('salary', '>', $salary);
        })->select();

        return json($res);
    }
}

在这里插入图片描述

字符串条件查询

对于一些实在复杂的查询,也可以直接使用原生SQL语句进行查询,例如:

Db::table('think_user')
    ->whereRaw('id > 0 AND name LIKE "thinkphp%"')
    ->select();

为了安全起见,我们可以对字符串查询条件使用参数绑定,例如:

Db::table('think_user')
    ->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])
    ->select();

快捷方法

系统封装了一系列快捷方法,用于简化查询

方法作用
whereOr字段OR查询
whereXor字段XOR查询
whereNull查询字段是否为Null
whereNotNull查询字段是否不为Null
whereIn字段IN查询
whereNotIn字段NOT IN查询
whereBetween字段BETWEEN查询
whereNotBetween字段NOT BETWEEN查询
whereLike字段LIKE查询
whereNotLike字段NOT LIKE查询
whereExistsEXISTS条件查询
whereNotExistsNOT EXISTS条件查询
whereExp表达式查询
whereColumn比较两个字段

动态查询

查询构造器还提供了动态查询机制,用于简化查询条件

动态查询描述
whereFieldName查询某个字段的值
whereOrFieldName查询某个字段的值
getByFieldName根据某个字段查询
getFieldByFieldName根据某个字段获取某个值
// 根据邮箱(email)查询用户信息
$user = Db::table('user')
	->whereEmail('thinkphp@qq.com')
    ->find();

// 根据昵称(nick_name)查询用户
$email = Db::table('user')
    ->whereNickName('like', '%流年%')
    ->select();
    
// 根据邮箱查询用户信息
$user = Db::table('user')
    ->getByEmail('thinkphp@qq.com');
    
// 根据昵称(nick_name)查询用户信息
$user = Db::table('user')
    ->field('id,name,nick_name,email')
    ->getByNickName('流年');
    
// 根据邮箱查询用户的昵称
$nickname = Db::table('user')
    ->getFieldByEmail('thinkphp@qq.com', 'nick_name');
    
// 根据昵称(nick_name)查询用户邮箱
$email = Db::table('user')
    ->getFieldByNickName('流年', 'email');

5) 子查询

使用 fetchSql()方法,可以设置不执行 SQL,而返回 SQL 语句,默认 true;
Db::name('user')->fetchSql(true)->select();
使用 buildSql()方法,也是返回 SQL 语句,不需要再执行 select(),且有括号
Db::name('user')->buildSql(true);
结合以上方法,我们实现一个子查询:

$subQuery = Db::table('think_user')
    ->field('id,name')
    ->where('id', '>', 10)
    ->buildSql();
Db::table($subQuery . ' a')
    ->where('a.name', 'like', 'thinkphp')
    ->order('id', 'desc')
    ->select();

子查询还有闭包模式,IN/NOT INEXISTS/NOT EXISTS之类的查询可以直接使用闭包作为子查询,例如:

Db::table('think_user')
    ->where('id', 'IN', function ($query) {
        $query->table('think_profile')->where('status', 1)->field('id');
    })
    ->select();

6) 原生查询

注意:V6.0.3+版本开始,原生查询仅支持Db类操作,不支持在模型中调用原生查询方法(包括query和execute方法)。
Db类支持原生SQL查询操作,主要包括query方法和execute方法

query方法用于执行SQL查询操作,返回查询结果数据集(数组)。

Db::query("select * from think_user where status=:id", ['id' => 1]);

execute用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回false,否则返回影响的记录数。

Db::execute("update think_user set name='thinkphp' where status=1");

支持在原生查询的时候使用参数绑定,包括问号占位符或者命名占位符,例如:

Db::query("select * from think_user where id=? AND status=?", [8, 1]);
// 命名绑定
Db::execute("update think_user set name=:name where status=:status", ['name' => 'thinkphp', 'status' => 1]);
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值