💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
>[danger]取消`resultset_type`配置参数 数据集查询结果不再受`resultset_type`配置参数影响,默认情况下,Db查询统一返回数组,模型查询统一返回模型对象和模型数据集对象。如果Db查询的时候也需要返回数据集的话,可以显式调用`fetchCollection`方法。 ## **查询单个数据** 查询单个数据使用`find`方法: ~~~ // table方法必须指定完整的数据表名 Db::table('think_user')->where('id', 1)->find(); //最终生成的SQL语句可能是: SELECT * FROM `think_user` WHERE `id` = 1 LIMIT 1 //多个条件查询,详情查看查询表达式 $where=[['id','>',2],['age','<',18]]; Db::table('think_user')->where($where)->find(); ~~~ >[danger] `find`方法查询结果不存在,返回`null`,否则返回结果数组 如果希望查询数据不存在的时候返回空数组,可以使用 ~~~ // table方法必须指定完整的数据表名 Db::table('think_user')->where('id', 1)->findOrEmpty(); ~~~ 如果希望在没有找到数据后抛出抛出一个`think\db\exception\DataNotFoundException`异常,可以使用 ~~~ Db::table('think_user')->where('id', 1)->findOrFail(); ~~~ ## **查询数据集(多个数据)** 查询多个数据(数据集)使用`select`方法: ~~~ Db::table('think_user')->where('status', 1)->select(); //最终生成的SQL语句可能是: SELECT * FROM `think_user` WHERE `status` = 1 //select方法查询结果是一个数据集对象,如果需要转换为数组可以使用 Db::table('think_user')->where('status', 1)->select()->toArray(); ~~~ 如果希望在没有查找到数据后抛出抛出一个`think\db\exception\DataNotFoundException`异常,可以使用 ~~~ $res=Db::table('think_user')->where('status',1)->selectOrFail(); //返回的数据集没有用toArray()转换位数组时,不能用empty($res)判断数据是否为空,而是使用isEmpty() if($res->isEmpty()){ } ~~~ 如果设置了数据表前缀参数的话,可以使用 ~~~ Db::name('user')->where('id', 1)->find(); Db::name('user')->where('status', 1)->select(); ~~~ >[danger] 如果你的数据表没有设置表前缀的话,那么`name`和`table`方法效果一致。 在`find`和`select`方法之前可以使用所有的链式操作(参考链式操作章节)方法。 ## **值和列查询** 查询某个字段的值可以用value() 查询结果不存在,返回 null ~~~ // 返回某个字段的值 Db::table('think_user')->where('id', 1)->value('name'); ~~~ 查询某一列的值可以用column(); 查询结果不存在,返回空数组 ~~~ // 返回数组 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'); ~~~ ## **数据分批处理** 如果你需要处理成千上百条数据库记录,可以考虑使用`chunk`方法,该方法一次获取结果集的一小块,然后填充每一小块数据到要处理的闭包,该方法在编写处理大量数据库记录的时候非常有用。 比如,我们可以全部用户表数据进行分批处理,每次处理 100 个用户记录: ~~~ Db::table('think_user')->chunk(100, function($users) { foreach ($users as $user) { // } }); ~~~ 你可以通过从闭包函数中返回`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`方法返回的是一个生成器对象,`user`变量是数据表的一条数据(数组)。 ~~~ $cursor = Db::table('user')->where('status', 1)->cursor(); foreach($cursor as $user){ echo $user['name']; } ~~~ ## **聚合查询** 在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等,ThinkPHP为这些统计操作提供了一系列的内置方法,包括: | 方法 | 说明 | | --- | --- | | count | 统计数量,参数是要统计的字段名(可选) | | max | 获取最大值,参数是要统计的字段名(必须) | | min | 获取最小值,参数是要统计的字段名(必须) | | avg | 获取平均值,参数是要统计的字段名(必须) | | sum | 获取总分,参数是要统计的字段名(必须) | >[danger] 聚合方法如果没有数据,默认都是0,聚合查询都可以配合其它查询条件 用法示例 ~~~ //获取用户数:SELECT COUNT(*) AS tp_count FROM `think_user` LIMIT 1 Db::table('think_user')->count(); //或者根据字段统计:SELECT COUNT(id) AS tp_count FROM `think_user` LIMIT 1 Db::table('think_user')->count('id'); //获取用户的最大积分:SELECT MAX(score) AS tp_max FROM `think_user` LIMIT 1 Db::table('think_user')->max('score'); //如果你要获取的最大值不是一个数值,可以使用第二个参数关闭强制转换 Db::table('think_user')->max('name',false); //获取积分大于0的用户的最小积分: Db::table('think_user')->where('score', '>', 0)->min('score'); Db::table('think_user')->where('score', '>', 0)->min('name',false); //获取用户的平均积分:SELECT AVG(score) AS tp_avg FROM `think_user` LIMIT 1 Db::table('think_user')->avg('score'); //统计用户的总成绩:SELECT SUM(score) AS tp_sum FROM `think_user` LIMIT 1 Db::table('think_user')->where('id',10)->sum('score'); ~~~ 如果你要使用`group`进行聚合查询,需要自己实现查询,例如 ~~~ Db::table('score')->field('user_id,SUM(score) AS sum_score')->group('user_id')->select(); ~~~ ## **子查询** 首先构造子查询SQL,可以使用下面三种的方式来构建子查询 **1、使用`fetchSql`方法** fetchSql方法表示不进行查询而只是返回构建的SQL语句,并且不仅仅支持`select`,而是支持所有的CURD查询。 ~~~ $subQuery = Db::table('think_user') ->field('id,name') ->where('id', '>', 10) ->fetchSql(true) ->select(); 生成的subQuery结果为: SELECT `id`,`name` FROM `think_user` WHERE `id` > 10 ~~~ **2、使用`buildSql`构造子查询** buildSql返回字sql语句的符串 ~~~ $subQuery = Db::table('think_user') ->field('id,name') ->where('id', '>', 10) ->buildSql(); 生成的subQuery结果为: ( SELECT `id`,`name` FROM `think_user` WHERE `id` > 10 ) ~~~ 调用`buildSql`方法后不会进行实际的查询操作,而只是生成该次查询的SQL语句(为了避免混淆,会在SQL两边加上括号),然后我们直接在后续的查询中直接调用。 然后使用子查询构造新的查询: ~~~ Db::table($subQuery . ' a') ->where('a.name', 'like', 'thinkphp') ->order('id', 'desc') ->select(); 生成的SQL语句为: SELECT * FROM ( SELECT `id`,`name` FROM `think_user` WHERE `id` > 10 ) a WHERE a.name LIKE 'thinkphp' ORDER BY `id` desc ~~~ **3、使用闭包构造子查询** `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(); 生成的SQL语句是 SELECT * FROM `think_user` WHERE `id` IN ( SELECT `id` FROM `think_profile` WHERE `status` = 1 ) ~~~ ~~~ Db::table('think_user') ->whereExists(function ($query) { $query->table('think_profile')->where('status', 1); })->find(); 生成的SQL语句为 SELECT * FROM `think_user` WHERE EXISTS ( SELECT * FROM `think_profile` WHERE `status` = 1 ) ~~~ >[danger] 除了上述查询条件外,比较运算也支持使用闭包子查询