天天看点

ThinkPHP5.1学习笔记 数据库操作

数据库

参见《Thinkphp5.1完全开发手册》学习

Mirror王宇阳

数据库连接

  • ThinkPHP采用内置抽象层对数据库操作进行封装处理;且基于PDO模式,可以适配各种数据库。
  • 数据库连接的配置文件(config/database.php)设置数据库的连接信息
    class DataTest extends Controller// 数据库连接
    { // url => http://localhost/tp5.1/public/index.php/index/data_test
        public function index()
        {
            $data = Db::table(\'tp_access\')->select();
            $data = Db::name(\'access\')->select();
            return json($data);
    
        }
    }
               

查询控制器(数据库操作)

想要查看SQL的执行语句细节可以配置:config/app.php -> app_trace => true;

开启后就可以在HTML页面右下角打开SQL语句的具体执行过程

注意:json输出的数据无法使用这一功能哦!

查询数据

查询单个数据使用

find

方法:

// table方法必须指定完整的数据表名
Db::table(\'think_user\')->where(\'id\',1)->find();
           

最终生成的SQL语句可能是:

SELECT * FROM `think_user` WHERE  `id` = 1 LIMIT 1
           
find 方法查询结果不存在,返回 null,否则返回结果数组

V5.1.23+

版本开始,支持

findOrEmpty

方法,当查询不存在的时候返回空数组而不是Null。

// table方法必须指定完整的数据表名
Db::table(\'think_user\')->where(\'id\',1)->findOrEmpty();
           

如果没有查找到数据,则会抛出一个

think\db\exception\DataNotFoundException

异常。

try{ //捕获异常
    // table方法必须指定完整的数据表名
    $data = Db::table(\'think_user\')->where(\'id\',1)->findOrEmpty();
} catch (DataNotFoundException $err) {
    return \'数据查询发送异常!\'
}
           

查询多个数据(数据集)使用

select

方法:

Db::table(\'think_user\')->where(\'status\',1)->select();
           

最终生成的SQL语句可能是:

SELECT * FROM `think_user` WHERE `status` = 1
           
select 方法查询结果是一个二维数组,如果结果不存在,返回空数组

如果希望在没有查找到数据后抛出异常可以使用

try{ //捕获异常
    $data = Db::table(\'think_user\')->where(\'status\',1)->selectOrFail();
} catch (DataNotFoundException $err) {
    return \'数据查询发送异常!\'
}
           
默认情况下,

find

select

方法返回的都是数组,区别在于后者是二维数组。

系统提供了一个

db

助手函数,可以更方便的查询:

db(\'user\')->where(\'id\',1)->find();
db(\'user\')->where(\'status\',1)->select();
           

db

方法的第一个参数的作用和

name

方法一样,如果需要使用不同的数据库连接,可以使用:

db(\'user\',\'db_config1\')->where(\'id\', 1)->find();
           

查询某个字段的值可以用 value(‘字段名’)

// 返回某个字段的值
Db::table(\'think_user\')->where(\'id\',1)->value(\'name\');	
           
value 方法查询结果不存在,返回 null

查询某一列的值可以用 colum(\'字段名/列名\')

// 返回数组
Db::table(\'think_user\')->where(\'status\',1)->column(\'name\');
// 指定id字段的值作为索引
Db::table(\'think_user\')->where(\'status\',1)->column(\'name\',\'id\');
           

如果要返回完整数据,并且添加一个索引值的话,可以使用

// 指定id字段的值作为索引 返回所有数据
Db::table(\'think_user\')->where(\'status\',1)->column(\'*\',\'id\');
           
column 方法查询结果不存在,返回空数组

数据分批处理可以使用 chunk

我们可以全部用户表数据进行分批处理,每次处理 100 个用户记录:

Db::table(\'think_user\')->chunk(100, function($users) {
    foreach ($users as $user) {
        //
    }
});
// 或者交给回调方法myUserIterator处理
Db::table(\'think_user\')->chunk(100, \'myUserIterator\');
           

你可以通过从闭包函数中返回

false

来中止对后续数据集的处理:

Db::table(\'think_user\')->chunk(100, function($users) {
    foreach ($users as $user) {
        // 处理结果集...
		if($user->status==0){
            return false;
        }
    }
});
           

也支持在

chunk

方法之前调用其它的查询方法,例如:

Db::table(\'think_user\')
->where(\'score\',\'>\',80)
->chunk(100, function($users) {
    foreach ($users as $user) {
        //
    }
});
           

chunk

方法的处理默认是根据主键查询,支持指定字段,例如:

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

并且支持指定处理数据的顺序。

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

chunk

方法一般用于命令行操作批处理数据库的数据,不适合WEB访问处理大量数据,很容易导致超时。

大批量数据处理

如果你需要处理大量的数据,可以使用新版提供的游标查询功能,该查询方式利用了PHP的生成器特性,可以大幅减少大量数据查询的内存占用问题。

$cursor = Db::table(\'user\')->where(\'status\', 1)->cursor();
foreach($cursor as $user){
	echo $user[\'name\'];
}
           

cursor

方法返回的是一个生成器对象,

user

变量是数据表的一条数据(数组)。

JSON类型数据查询(

mysql

// 查询JSON类型字段 (info字段为json类型)
Db::table(\'think_user\')
	->where(\'info->email\',\'[email protected]\')
	->find();
           
链式查询简单认识
  • 查询规则
    • 通过指向符号

      ->

      多次连续的调用方法
      Db::table(\'think_user\')
          ->where(\'status\',1)
          ->order(\'create_time\')
          ->limit(10)
          ->select();
                 
    • 多次i的调用使用返回的都是数据库对象,可以多次的链式查询数据对象的方法
    • 最后的数据库对象可以使用 find()、select() 等结果方法,返回数据结果
    • find()、select()、value()、column() 是结果查询方法,并不是链式查询方法
  • 链式查询方法:

    系统支持的链式操作方法包含:

    连贯操作 作用 支持的参数类型
    where* 用于AND查询 字符串、数组和对象
    whereOr* 用于OR查询 字符串、数组和对象
    wheretime* 用于时间日期的快捷查询 字符串
    table 用于定义要操作的数据表名称 字符串和数组
    alias 用于给当前数据表定义别名 字符串
    field* 用于定义要查询的字段(支持字段排除) 字符串和数组
    order* 用于对结果排序 字符串和数组
    limit 用于限制查询结果数量 字符串和数字
    page 用于查询分页(内部会转换成limit) 字符串和数字
    group 用于对查询的group支持 字符串
    having 用于对查询的having支持 字符串
    join* 用于对查询的join支持 字符串和数组
    union* 用于对查询的union支持 字符串、数组和对象
    view* 用于视图查询 字符串、数组
    distinct 用于查询的distinct支持 布尔值
    lock 用于数据库的锁机制 布尔值
    cache 用于查询缓存 支持多个参数
    relation* 用于关联查询 字符串
    with* 用于关联预载入 字符串、数组
    bind* 用于数据绑定操作 数组或多个参数
    comment 用于SQL注释 字符串
    force 用于数据集的强制索引 字符串
    master 用于设置主服务器读取数据 布尔值
    strict 用于设置是否严格检测字段名是否存在 布尔值
    sequence 用于设置Pgsql的自增序列名 字符串
    failException 用于设置没有查询到数据是否抛出异常 布尔值
    partition 用于设置分表信息 数组 字符串
    所有的连贯操作都返回当前的模型实例对象(this),其中带*标识的表示支持多次调用。
  • 更多查询

    多次查询并不需要每次都创建一个实例;可以保存实例对象进行反复调用:

    $user = Db::name(\'user\');
    $data = $user->select();
               
    public function getModelData()
        {
            $book = Db::table(\'tp_book\');     // 创建tp_book的实例并保持$book
            $data = $book->select();
            return json($data);
            $data1 = $book->where(\'id\',1)->column(\'title\');
            //使用被保持的实例
            return json($data1); // 结果返回 莎士比亚
            $data2 = $book->column(\'title\');
            // 被保存的实例会保留上一个查询结果(对象)
            return json($data3); // 结果返回 与 $data2 一致
        }
               
    实例会保存上一个查询对象结果,但使用

    removerOption()

    方法可以清理上一个保留的值
    $data3 = $book->removeOption(\'where\')->column(\'title\');
    return json($data3); // 结果返回 没有where条件限制了
               
增删改操作

新增数据

ThinkPHP5.1使用

insert()

insertGetId()

方法向数据表添加一条数据

使用

Db

类的

insert

方法向数据库提交数据

$data = [\'foo\' => \'bar\', \'bar\' => \'foo\'];
// 笔者在insert()的时候,发现中文内容添加后会在数据库中显示空白
Db::name(\'user\')->insert($data);
           

insert

方法添加数据成功返回添加成功的条数,通常情况返回 1
// 新增数据到数据表中
    public function insert()
    {
        $book = Db::table(\'tp_book\');
        // 匹配添加数据
        $data = [ // 可为空Null的、自动增补的可以忽略不添加
            \'user_id\'    =>  \'66\',
            \'title\'      =>  \'Mirror\'
        ];

        $book->insert($data);

        $select = $book->select();
        return json($select);
    }
           

或者使用

data

方法配合

insert

使用。

$data = [\'foo\' => \'bar\', \'bar\' => \'foo\'];
Db::name(\'user\')
    ->data($data)
    ->insert();
           
如果你的数据表里面没有

foo

或者

bar

字段,那么就会抛出异常。

如果不希望抛出异常,可以使用下面的方法:

$data = [\'foo\' => \'bar\', \'bar\' => \'foo\'];
Db::name(\'user\')->strict(false)->insert($data);
           

不存在的字段的值将会直接抛弃。

如果是mysql数据库,支持

replace

写入,例如:

$data = [\'foo\' => \'bar\', \'bar\' => \'foo\'];
Db::name(\'user\')->insert($data, true);
           

添加数据后如果需要返回新增数据的自增主键,可以使用

insertGetId

方法新增数据并返回主键值:

$userId = Db::name(\'user\')->insertGetId($data);
           

insertGetId

方法添加数据成功返回添加数据的自增主键

添加多条数据直接向 Db 类的

insertAll

方法传入需要添加的数据即可

public  function insertAll()//批量添加到数据表
    {
        $dataAll = [
            [
                \'user_id\'    =>  \'66\',
                \'title\'      =>  \'《白帽子讲Web安全》\'
            ],
            [
                \'user_id\'   => \'88\',
                \'title\'     => \'《乔布斯传》\'
            ],
            [
                \'user_id\'   => \'99\',
                \'title\'     => \'《白夜行》\'
            ],
        ];


        $kk = Db::table(\'tp_book\')->insertAll($dataAll);
        return $kk;
    }
           
insertAll 方法添加数据成功返回添加成功的条数

如果批量插入的数据比较多,可以指定分批插入,使用

limit

方法指定每次插入的数量限制。

$data = [
    [\'foo\' => \'bar\', \'bar\' => \'foo\'],
    [\'foo\' => \'bar1\', \'bar\' => \'foo1\'],
    [\'foo\' => \'bar2\', \'bar\' => \'foo2\']
    ...
];
// 分批写入 每次最多100条数据
Db::name(\'user\')->data($data)->limit(100)->insertAll();
           

修改数据

// 修改数据
    public function update()
    {
        $date = [
            \'title\'     =>  \'《解忧杂货铺》\'
        ];

        $kk = Db::table(\'tp_book\')->where(\'user_id\',\'99\')->update($date);
        return $kk;
    }
           
update 方法返回影响数据的条数,没修改任何数据返回 0

如果数据中包含主键,可以直接使用:

Db::name(\'user\')
    ->update([\'name\' => \'thinkphp\',\'id\'=>1]);
           

如果要更新的数据需要使用

SQL

函数或者其它字段,可以使用下面的方式:

Db::name(\'user\')
    ->where(\'id\',1)
    ->inc(\'read_time\') //对字段增值
    ->dec(\'score\',3) //对字段减值
    ->exp(\'name\',\'UPPER(name)\') // 在字段中使用mysql函数
    ->update();
           

可以使用

setInc/setDec

方法自增或自减一个字段的值( 如不加第二个参数,默认步长为1)。

// score 字段加 1
Db::table(\'think_user\')
    ->where(\'id\', 1)
    ->setInc(\'score\');
// score 字段加 5
Db::table(\'think_user\')
    ->where(\'id\', 1)
    ->setInc(\'score\', 5);
// score 字段减 1
Db::table(\'think_user\')
    ->where(\'id\', 1)
    ->setDec(\'score\');
// score 字段减 5
Db::table(\'think_user\')
    ->where(\'id\', 1)
    ->setDec(\'score\', 5);
           

setInc/setDec

支持延时更新,如果需要延时更新则传入第三个参数,下例中延时10秒更新。

Db::name(\'user\')->where(\'id\', 1)->setInc(\'score\', 1, 10);
           

V5.1.7+

版本以后,支持使用

raw

方法进行数据更新,适合在数组更新的情况。

Db::name(\'user\')
    ->where(\'id\', 1)
    ->update([
        \'name\'		=>	Db::raw(\'UPPER(name)\'),
        \'score\'		=>	Db::raw(\'score-3\'),
        \'read_time\'	=>	Db::raw(\'read_time+1\')
    ]);
           

字段值更新 setField(\'原字段名\',\'新字段名\')

Db::name(\'user\')
    ->where(\'id\',1)
    ->setField(\'name\', \'thinkphp\');
           

删除数据

// 根据主键删除
Db::table(\'think_user\')->delete(1);
Db::table(\'think_user\')->delete([1,2,3]);

// 条件删除    
Db::table(\'think_user\')->where(\'id\',1)->delete();
Db::table(\'think_user\')->where(\'id\',\'<\',10)->delete();

// 无条件删除所有数据
Db::name(\'user\')->delete(true);

           
查询表达式

比较查询

Db::name(\'book\')->where(\'id\',80)->find();  		//简写
Db::name(\'book\')->where(\'id\',\'=\',80)->find();   //完整;且与第一条同意义 
           

5.1

还支持新的查询方法

whereField(\'表达式\',\'查询条件\');
whereOrField(\'表达式\',\'查询条件\');	
           

Field

使用字段的驼峰命名方式。
  • where() 格式
    where( 字段名 , 表达式 , 查询条件);
               
    表达式包含以下:
    表达式 含义 快捷查询方法
    = 等于
    <> 不等于
    > 大于
    >= 大于等于
    < 小于
    <= 小于等于
    [NOT] LIKE 模糊查询

    whereLike/whereNotLike

    [NOT] BETWEEN (不在)区间查询

    whereBetween/whereNotBetween

    [NOT] IN (不在)IN 查询

    whereIn/whereNotIn

    [NOT] NULL 查询字段是否(不)是NULL

    whereNull/whereNotNull

    [NOT] EXISTS EXISTS查询

    whereExists/whereNotExists

    [NOT] REGEXP 正则(不)匹配查询 (仅支持Mysql)
    [NOT] BETWEEM TIME 时间区间比较 whereBetweenTime
    > TIME 大于某个时间

    whereTime

    < TIME 小于某个时间

    whereTime

    >= TIME 大于等于某个时间

    whereTime

    <= TIME 小于等于某个时间

    whereTime

    EXP 表达式查询,支持SQL语法

    whereExp

区间查询(建议使用快捷)

  • link 表达式进行模糊查询
    $data = Db::table(\'tp_book\')->where(\'title\',\'like\',\'%白%\')->column(\'title\');
    return json($data);
               
    支持使用数组
    // 查询 title中包含 白和M开头的书籍
    $data = Db::table(\'tp_book\')
        ->where(\'title\',\'like\',[\'%白%\',\'M%\'],\'OR\')
        ->column(\'title\');
    return json($data);
               
    为了更加方便,应该直接使用

    whereLike

    方法
    Db::name(\'user\')->whereLike(\'name\',\'thinkphp%\')->select();
    Db::name(\'user\')->whereNotLike(\'name\',\'thinkphp%\')->select();
               
  • between 指定区间范围查找

    查询条件支持字符串或者数组,例如:

    Db::name(\'user\')->where(\'id\',\'between\',\'1,8\')->select();
               
    和下面的等效:
    Db::name(\'user\')->where(\'id\',\'between\',[1,8])->select();
               
    最快捷的查询方法是:
    Db::name(\'user\')->whereBetween(\'id\',\'1,8\')->select();
    Db::name(\'user\')->whereNotBetween(\'id\',\'1,8\')->select();
               
  • in 指定索引查找
    // in、not in 指定所有查找
    $data = Db::table(\'tp_book\')->where(\'id\',\'in\',\'1,2,23\')->column(\'title\');
    $data = Db::table(\'tp_book\')->where(\'id\',\'in\',\'[1,2,23]\')->column(\'title\');
    
    $data = Db::table(\'tp_book\')->whereIn(\'id\',\'1,2,34\')->column(\'title\');
    $data = Db::table(\'tp_book\')->whereNotIn(\'id\',\'1,2,3,4,44\')->column(\'title\');
    return json($data);
               
  • Null 查询字段是否(不)是

    Null

    // null、not null 查询指定字段是否可以为Null/Not Null
    $data = Db::table(\'tp_access\')->where(\'details\',\'null\')->column(\'user_id\');
    $data = Db::table(\'tp_access\')->where(\'details\',\'notnull\')->column(\'user_id\');
    $data = Db::table(\'tp_access\')->whereNull(\'details\')->column(\'user_id\');
    $data = Db::table(\'tp_access\')->whereNotNull(\'details\')->column(\'user_id\');
    return json($data);
               

EXP:其它查询

支持更复杂的查询情况 例如:

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

可以改成:

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

exp

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

$data = Db::table(\'tp_access\')->where(\'id\',\'exp\',\'in (1,2,3,4)\')->column(\'user_id\');// 快捷 ↓
$data = Db::table(\'tp_access\')->whereExp(\'id\',\'in (1,2,3,4)\')->column(\'user_id\');
// 等效于 ==> SELECT `user_id` FROM `tp_access` WHERE ( `id` in (1,2,3,4) )

$data = Db::table(\'tp_book\')->whereExp(\'id\',\'>=20 and user_id =88 \')->column(\'title\');
$data = Db::table(\'tp_book\')->whereExp(\'\',\'id >=20 and user_id =88 \')->column(\'title\');
// 等效于 ==> SELECT `title` FROM `tp_book` WHERE ( `id` >=20 and user_id =88 )
print_r($data);
           

时间查询

  • 传统查询 where()

    where

    方法支持时间比较,例如:
    // 采用比较符号比较时间
    $data = Db::table(\'tp_one\')->where(\'create_time\',\'< time\',\'2016-10-10 00:00:00\')->select();
    // ==> SELECT * FROM `tp_one` WHERE `create_time` < \'2016-10-10 00:00:00\'
    // 在第二参数明确 time 的时候,第三个参数会自动按照完整的time格式填充(年-月-日 时:分:秒)
    
    // 时间区间查询
    where(\'create_time\', \'between time\', [\'2015-1-1\', \'2016-1-1\']);
               
    第三个参数可以传入任何有效的时间表达式,会自动识别你的时间字段类型,支持的时间类型包括

    timestamps

    datetime

    date

    int

    区间查询

    whereTime()

    /

    wherebetween()

    /

    wherebetweenTime()

    :
    // 采用whereTime()区间查询时间 (whereTime()和between time 结果是一样的,推荐后者)
    $data = Db::table(\'tp_one\')
        ->where(\'create_time\',\'between time\',[\'2018-01-01\',\'2019-01-01\'])
        ->select();
    $data = Db::table(\'tp_one\')
        ->whereTime(\'create_time\',[\'2018-01-01\',\'2019-01-01\'])
        ->select();
    // ==> SELECT * FROM `tp_one` WHERE `create_time` BETWEEN \'2018-01-01 00:00:00\' AND \'2019-01-01 00:00:00\'
    // wherebetween() 也支持如上的区间Time查询
    $data = Db::table(\'tp_one\')
        ->whereBetween(\'create_time\',[\'2018-01-01\',\'2019-01-01\'])
        ->select();
    // wherebetweenTime() 也是一个支持时间起始查询函数
    $data = Db::table(\'tp_one\')
        ->whereBetweenTime(\'create_time\',\'2018-01-01\',\'2019-01-01\')
        ->select();
    // 如果第三个参数为空则代表查询当天(一天)
               

    whereTime()

    还支持时间便捷固定查询:
    关键字 (whereTime()的第三个参数值) 说明
    today 今天
    yesterday 昨天
    week 本周
    last week 上周
    month 本月
    last month 上月
    year 本年
    last year 去年
    同时还支持指定的时间数据查询;例如两小时内就是:

    -2 hour

    whereBetweenTimeField()

    多时间(字)段查询

    V5.1.17+

    版本开始,可以支持对两个时间字段的区间比较
    // 查询有效期内的活动
    Db::name(\'event\')
    	->whereBetweenTimeField(\'start_time\',\'end_time\')
        ->select();	
               
    上面的查询相当于
    // 查询有效期内的活动
    Db::name(\'event\')
    	->whereTime(\'start_time\', \'<=\', time())
        ->whereTime(\'end_time\', \'>=\', time())
        ->select();
               
聚合查询

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

方法 说明
count 统计数量,参数是要统计的字段名(可选)
max 获取最大值,参数是要统计的字段名(必须)
min 获取最小值,参数是要统计的字段名(必须)
avg 获取平均值,参数是要统计的字段名(必须)
sum 获取总分,参数是要统计的字段名(必须)
聚合方法如果没有数据,默认都是0,聚合查询都可以配合其它查询条件

V5.1.5+

版本开始,聚合查询可以支持

JSON

字段类型(MySQL5.7+开始支持JSON)

count()

统计数量: 可以根据表的行数或根据字段的行数

$data = Db::table(\'tp_book\')->count();
// ==> SELECT COUNT(*) AS tp_count FROM `tp_book`
$data = Db::table(\'tp_book\')->count(\'id\');
// ==> SELECT COUNT(`id`) AS tp_count FROM `tp_book`
           

max()/min()

获取最值:可以根据字段名获取字段列中最值;如果字段中的不是数值,函数会自动强制转换,可以通过定义第二参数为“false”来取消强制转换的行为

// max()/min() 最值函数
$data = Db::table(\'tp_book\')
    ->max(\'user_id\');
// ==> SELECT MAX(`user_id`) AS tp_max FROM `tp_book`
$data = Db::table(\'tp_book\')
    ->max(\'title\');
$data = Db::table(\'tp_book\')
    ->max(\'title\',false); // 和↑条同作用,但是这条将不强制转换,按照编码进行
// ==> SELECT MAX(`title`) AS tp_max FROM `tp_book`
           

avg()

平均值计算

$data = Db::table(\'tp_book\')->avg(\'user_id\');
// ==> SELECT AVG(`user_id`) AS tp_avg FROM `tp_book`   
           

sum()

求和计算

$data = Db::table(\'tp_book\')->sum(\'user_id\');
// ==> SELECT SUM(`user_id`) AS tp_sum FROM `tp_book`
           
子查询
  • 使用

    fetchSql()

    方法,不执行SQL语句而是返回SQL语句,默认True
    $subQuery = Db::table(\'think_user\')
        ->field(\'id,name\')
        ->where(\'id\', \'>\', 10)
        ->fetchSql(true)
        ->select();
               
    生成的subQuery结果为:
    SELECT `id`,`name` FROM `think_user` WHERE `id` > 10 
               
  • 使用

    buidSql()

    方法,返回SQL语句且不需要执行select()同时添加两侧括号
    $subQuery = Db::table(\'think_user\')
        ->field(\'id,name\')
        ->where(\'id\', \'>\', 10)
        ->buildSql();
               
    生成的subQuery结果为:
    ( SELECT `id`,`name` FROM `think_user` WHERE `id` > 10 )
               
在SQL语句中我们需要用到子查询的功能,就是利用SQL1语句的查询结果给SQL2语句使用

原生SQL语句:(具备子查询)

SELECT * FROM `tp_one` WHERE id in (SELECT uid FROM tp_two where gender = \'男\');
           

构造ThinkPHP的子查询代码:

$sql_1 = Db::table(\'tp_two\')
    ->field(\'uid\')
    // field()方法主要作用是标识要返回或者操作的字段,可以用于查询和写入操作。
    ->where(\'gender\',\'男\')
    ->buildSql();
$sql = Db::table(\'tp_one\')
    ->whereIn(\'id\',$sql_1)
    ->select();
// ==> SELECT * FROM `tp_one` WHERE `id` = ( SELECT `uid` FROM `tp_two` WHERE `gender` = \'男\' )
// 这里使用WhereIn出现的问题就是原本应该是 IN 却变成了 = 符号

$sql_exp =  Db::table(\'tp_one\')
    ->whereExp(\'id\',\'IN\'.$sql_1)
    ->select();
// ==> SELECT * FROM `tp_one` WHERE ( `id` IN( SELECT `uid` FROM `tp_two` WHERE `gender` = \'男\' ) )
// 由于whereIn无法正确的使用,于是采用whereExp()方法构造IN并使用连接符连接$sql_1
           

使用闭包构造子查询

IN/NOT IN

EXISTS/NOT EXISTS

之类的查询可以直接使用闭包作为子查询,例如:

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

query()/读操作

query

方法用于执行

SQL

查询操作,如果数据非法或者查询错误则返回false,否则返回查询结果数据集(同

select

方法)。

使用示例:

Db::query("select * from think_user where status=1");
           

execute()/写操作

execute

用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回

false

,否则返回影响的记录数。

使用示例:

Db::execute("update think_user set name=\'thinkphp\' where status=1");
           
链式查询-建议参考手册

where

  • 表达式查询:即之前的那些普通的多个表达式组合的查询方式

    例如:where比较查询、whereIn、whereLike……

  • 关联数组查询:等值AND和IN函数条件
    // Where数组关联查询可以等值AND和IN函数条件
    $data = Db::table(\'tp_one\')->where([
        \'math\'      =>  88,
        \'chinese\'   =>  88,
    ])->select();
    // ==> SELECT * FROM `tp_one` WHERE `math` = 88 AND `chinese` = 88
    $data = Db::table(\'tp_one\')->where([
        \'math\'      =>  88,
        \'chinese\'   =>  [88,99,11],//等效于IN (88,99,11)
    ])->select();
    // ==> SELECT * FROM `tp_one` WHERE `math` = 88 AND `chinese` IN (88,99,11)
               
  • 索引数组查询:批量设置查询条件
    // Where索引数组查询
    $data = Db::table(\'tp_one\')->where([
    		[\'math\',\'<=\',\'88\'],
    		[\'chinese\',\'>\',\'90\'],
    	])->select();
    // ==>  SELECT * FROM `tp_one` WHERE `math` <= 88 AND `chinese` > 90
               
    如果需要事先组装数组查询条件,可以使用:
    $map[] = [\'name\',\'like\',\'think\'];
    $map[] = [\'status\',\'=\',1];
               
    数组的各种查询方式其实可以多样应用
  • 字符串传递

    使用字符串条件直接查询和操作,例如:

    Db::table(\'think_user\')->where(\'type=1 AND status=1\')->select(); 
               
    最后生成的SQL语句是
    SELECT * FROM think_user WHERE type=1 AND status=1
               
这里的where多样运用需要开发者按照自己的喜好和实际的开发需求决定如何使用;如果无法运用就直接使用原生!

table

table

方法主要用于指定操作的数据表。

Db::table(\'think_user\')->where(\'status>1\')->select(); // 指定数据表
Db::table(\'db_name.think_user\')->where(\'status>1\')->select(); //指定数据库和表
           

如果需要对多表进行操作,可以这样使用:

Db::field(\'user.name,role.title\')
->table(\'think_user user,think_role role\')
->limit(10)->select();
           

为了尽量避免和mysql的关键字冲突,可以建议使用数组方式定义,例如:

Db::field(\'user.name,role.title\')
->table([\'think_user\'=>\'user\',\'think_role\'=>\'role\'])
->limit(10)->select();
           

使用数组方式定义的优势是可以避免因为表名和关键字冲突而出错的情况。

alias

alias

用于设置当前数据表的别名,便于使用其他的连贯操作;例如join方法等。

示例:

Db::table(\'think_user\')
->alias(\'a\')
->join(\'think_dept b \',\'b.user_id= a.id\')
->select();
           

最终生成的SQL语句类似于:

SELECT * FROM think_user a INNER JOIN think_dept b ON b.user_id= a.id
           

field

field

方法主要作用是标识要返回或者操作的字段,可以用于查询和写入操作。

  • 指定字段:field()可以在查询数据、添加数据中都可以运用到,但是在添加中不得违背SQL的规范
    $data = Db::table(\'tp_book\')
        ->where(\'user_id\',\'>\',\'50\')
        ->field(\'title\')
        ->select();
    // ==> SELECT `title` FROM `tp_book` WHERE `user_id` > 50
    
               
  • 使用SQL函数
    $data = Db::table(\'tp_one\')
        ->field(\'SUM(math)\')
        ->select();
    // ==> SELECT SUM(math) FROM `tp_one`
               
  • field方法的参数可以支持数组,例如:
    Db::table(\'think_user\')->field([\'id\',\'title\',\'content\'])->select();
               
  • 字段排除:排除某一个或多个字段,需要在field()的第二参数设置为True默认Falst
    // 排除某一个或多个字段,需要在field()的第二参数设置为True  不支持跨表和join操作。
    $data = Db::table(\'tp_book\')->field(\'user_id\',true)->select();
    // ==> SELECT `id`,`title` FROM `tp_book`
    $data = Db::table(\'tp_book\')->field(\'id,user_id\',true)->select();
    // ==>   SELECT `title` FROM `tp_book`
               

strict

strict

方法用于设置是否严格检查字段名,用法如下:(建议true)

// 关闭字段严格检查
Db::name(\'user\')
    ->strict(false)
    ->insert($data);
           

注意,系统默认值是由数据库配置参数

fields_strict

决定,因此修改数据库配置参数可以进行全局的严格检查配置,如下:

// 关闭严格检查字段是否存在
\'fields_strict\'  => false,
           
如果开启字段严格检查的话,在更新和写入数据库的时候,一旦存在非数据表字段的值,则会抛出异常。

limit

limit()

用于限制输入输出的数据条数,也可以指定输出的行数范围

// limit() 可以指定输出的条数、行数范围、输入的条数限制
$data = Db::table(\'tp_book\')->field(\'title\')->limit(3)->select(); //限制条数
// ==>  SELECT `title` FROM `tp_book` LIMIT 3
$data = Db::table(\'tp_book\')->field(\'title\')->limit(3,3)->select(); // 实现分页
// ==> SELECT `title` FROM `tp_book` LIMIT 3,3 //limit(起始行,条数)
           

limit

方法也可以用于写操作,例如更新满足要求的3条数据:

Db::table(\'think_user\')
->where(\'score\',100)
->limit(3)
->update([\'level\'=>\'A\']);
           

page

page()

方法主要用于分页查询。

// page() 分页查询
$data = Db::table(\'tp_book\')->field(\'title\')->page(1,3)->select();
// =>  SELECT `title` FROM `tp_book` LIMIT 0,3
$data = Db::table(\'tp_book\')->field(\'title\')->page(2,3)->select();
// =>  SELECT `title` FROM `tp_book` LIMIT 3,3
           

page()直接是规定第一页第二页即可,page()方法自动实现LIMIT的分页补充……而当LIMIT和page同时出现的话,page接受的一个参数代表页数,而limit的参数代表输出的每页条数。(具体见手册)

order

order()

方法用于对操作的结果排序或者优先级限制。(参考手册)

Db::table(\'think_user\')
->where(\'status\', 1)
->order(\'id\', \'desc\')
->limit(5)
->select();
 SELECT * FROM `think_user` WHERE `status` = 1 ORDER BY `id` desc LIMIT 5
           
如果没有指定

desc

或者

asc

排序规则的话,默认为

asc

支持使用数组对多个字段的排序,例如:

Db::table(\'think_user\')
->where(\'status\', 1)
->order([\'order\',\'id\'=>\'desc\'])
->limit(5)
->select(); 
           

最终的查询SQL可能是

SELECT * FROM `think_user` WHERE `status` = 1 ORDER BY `order`,`id` desc LIMIT 5
           

对于更新数据或者删除数据的时候可以用于优先级限制

Db::table(\'think_user\')
->where(\'status\', 1)
->order(\'id\', \'desc\')
->limit(5)
->delete(); 
           

生成的SQL

DELETE FROM `think_user` WHERE `status` = 1 ORDER BY `id` desc LIMIT 5
           

V5.1.7+

版本开始,如果你需要在

order

方法中使用mysql函数的话,必须使用下面的方式:

Db::table(\'think_user\')
->where(\'status\', 1)
->orderRaw("field(name,\'thinkphp\',\'onethink\',\'kancloud\')")
->limit(5)
->select();
           

group

GROUP

方法通常用于结合合计函数,根据一个或多个列对结果集进行分组 。(参考手册)

group

方法只有一个参数,并且只能使用字符串。

例如,我们都查询结果按照用户id进行分组统计:

Db::table(\'think_user\')
    ->field(\'user_id,username,max(score)\')
    ->group(\'user_id\')
    ->select();
           

生成的SQL语句是:

SELECT user_id,username,max(score) FROM think_score GROUP BY user_id
           

也支持对多个字段进行分组,例如:

Db::table(\'think_user\')
    ->field(\'user_id,test_time,username,max(score)\')
    ->group(\'user_id,test_time\')
    ->select();
           

生成的SQL语句是:

SELECT user_id,test_time,username,max(score) FROM think_user GROUP BY user_id,test_time
           

having

HAVING

方法用于配合group方法完成从分组的结果中筛选(通常是聚合条件)数据。

having

方法只有一个参数,并且只能使用字符串,例如:

Db::table(\'think_user\')
    ->field(\'username,max(score)\')
    ->group(\'user_id\')
    ->having(\'count(test_time)>3\')
    ->select(); 
           

生成的SQL语句是:

SELECT username,max(score) FROM think_score GROUP BY user_id HAVING count(test_time)>3