数据库的时间查询
传统方式
- 可以使用
>
,<
,>=
,<=
来筛选匹配时间的数据;
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();
聚合.原生.子查询
聚合查询
- 使用
count
方法,可以求出所查询数据的数量;
Db::name('user')->count();
count()
可设置指定id
,比如有空值Null
的uid
,不会计算数量;
Db::name('user')->count('uid');
- 使用
max
方法,求出所查询数据字段的最大值;
Db::name('user')->max('price');
- 如果
max
方法,求出的值不是数值,则通过第二参数强制转换;
Db::name('user')->max('price', false);
- 使用
min
方法,求出所查询数据字段的最小值,也可以强制转换;
Db::name('user')->min('price');
- 使用
avg
方法,求出所查询数据字段的平均值;
Db::name('user')->avg('price');
- 使用
sum
方法,求出所查询数据字段的总和;
Db::name('user')->sum('price');
子查询
- 使用
fetchSql
方法,可以设置不执行SQL,而返回SQL语句,默认true
;
Db::name('user')->fetchSql(true)->select();
- 使用
buildSql
方法,也是返回SQL语句,不需要再执行select()
,且有括号;
Db::name('user')->buildSql(true);
- 结合以上方法,我们实现一个子查询;
$subQuery = Db::name('two')->field('uid')->where('gender','男')->buildSql(true);
$result = Db::name('one')->where('id','exp','IN '.$subQuery)->select();
- 使用闭包的方式执行子查询;
$result = Db::name('one')->where('id', 'in', function ($query) {
$query->name('two')->where('gender', '男')->field('uid');
})->select();
原生查询
- 使用
query
方法,进行原生SQL查询,适用于读取操作,SQL错误返回false
;
Db::query('select * from tp_user');
- 使用
execute
方法,进行原生SQL更新写入等,SQL错误返回false
;
Db::execute('update tp_user set username="孙悟空" where id=29');
链式查询方法
where
- 表达式查询,就是
where()
方法的基础查询方式;
Db::name('user')->where('id', '>', 70)->select();
- 关联数组查询,通过键值对来数组键值对匹配的查询方式;
$user = Db::name('user')->where([
'gender' => '男',
'price' => 100 ,
//'price' => [60,70,80],
])->select();
- 索引数组查询,通过数组里的数组拼装方式来查询;
$user = Db::name('user')->where([
['gender', '=', '男'],
['price', '=', '100']
])->select();
- 将复杂的数组组装后,通过变量传递,将增加可读性;
$map[] = ['gender', '=', '男'];
$map[] = ['price', 'in', [60, 70, 80]];
$user = Db::name('user')->where($map)->select();
- 字符串形式传递,简单粗暴的查询方式,
whereRaw()
支持复杂字符串格式;
Db::name('user')->whereRaw('gender="男" AND price IN (60, 70, 80)')->select();
- 如果SQL查询采用了预处理模式,比如
id=:id
,也能够支持;
Db::name('user')->whereRaw('id=:id', ['id'=>19])->select();
field
- 使用
field
方法,可以指定要查询的字段;
Db::name('user')->field('id, username, email')->select();
Db::name('user')->field(['id', 'username', 'email'])->select();
- 使用
field
方法,给指定的字段设置别名;
Db::name('user')->field('id,username as name')->select();
Db::name('user')->field(['id', 'username'=>'name'])->select();
- 在
fieldRaw
方法里,可以直接给字段设置MySQL函数;
Db::name('user')->fieldRaw('id,SUM(price)')->select();
- 使用
field(true)
的布尔参数,可以显式的查询获取所有字段,而不是*;
Db::name('user')->field(true)->select();
- 使用
withoutField
方法中字段排除,可以屏蔽掉想要不显示的字段;
Db::name('user')->withoutField('details')->select();
- 使用
field
方法在新增时,验证字段的合法性;
Db::name('user')->field('username, email, details')->insert($data);
alias
- 使用
alias
方法,给数据库起一个别名;
Db::name('user')->alias('a')->select();
limit
- 使用
limit()
方法,限制获取输出数据的个数;
Db::name('user')->limit(5)->select();
- 分页模式,即传递两个参数,比如从第3条开始显示5条
limit(2,5)
;
Db::name('user')->limit(2, 5)->select();
- 实现分页,需要严格计算每页显示的条数,然后从第几条开始;
//第一页
Db::name('user')->limit(0, 5)->select();
//第二页
Db::name('user')->limit(5, 5)->select();
page
page()
分页方法,优化了limit()
方法,无须计算分页条数;
//第一页
Db::name('user')->page(1, 5)->select();
//第二页
Db::name('user')->page(2, 5)->select();
order
- 使用
order()
方法,可以指定排序方式,没有指定第二参数,默认asc
;
Db::name('user')->order('id', 'desc')->select();
- 支持数组的方式,对多个字段进行排序;
Db::name('user')->order(['create_time'=>'desc', 'price'=>'asc'])->select();
- 使用
orderRaw()
方法,支持排序的时候指定MySQL函数;
Db::name('user')->orderRaw('FIELD(username,"樱桃小丸子") DESC')->select();
group
- 使用
group()
方法,给性别不同的人进行price
字段的总和统计;
Db::name('user')->fieldRaw('gender, SUM(price)')->group('gender')->select();
- 也可以进行多字段分组统计;
Db::name('user')->fieldRaw('gender, SUM(price)')->group('gender,password')->select();
having
- 使用
group()
分组之后,再使用having()
进行筛选;
$result = Db::name('user')
->fieldRaw('gender, SUM(price)')
->group('gender')
->having('SUM(price)>600')
->select();
数据库的高级查询
高级查询
- 使用
|(OR)
或&(AND)
来实现where
条件的高级查询,where
支持多个连缀;
$result = Db::name('user')
->where('username|email', 'like', '%xiao%')
->where('price&uid', '>', 0)
->select();
- 关联数组方式,可以在
where
进行多个字段进行查询;
$result = Db::name('user')->where([
['id', '>', 0],
['status', '=', 1],
['price', '>=', 80],
['email', 'like', '%163%']
])->select();
- 根据之前的课程中,条件字符串复杂组装,比如使用
exp
了,就使用raw()
方法;
$result = Db::name('user')->where([
['status', '=', 1],
['price', 'exp', Db::raw('>80')]
])->select();
- 如果有多个
where
,并且where
条件是分离的$map
,而$map
本身有多个条件; - 那么
$map
条件如果需要先执行出结果,再和后续条件判断,也就是加上括号; - 那么,需要对这个
$map
变量,再加上一个中括号处理优先级;
$map = [
['status', '=', 1],
['price', 'exp', Db::raw('>80')]
];
$result = Db::name('user')
->where([$map])
->where('status', '=', '%163.com%')->select();
- 如果,条件中有多次出现一个字段,并且需要 OR 来左右筛选,可以用 whereOr;
$map1 = [
['username', 'like', '%小%'],
['email', 'like', '%163%']
];
$map2 = [
['username', 'like', '%孙%'],
['email', 'like', '%.com%']
];
$result = Db::name('user')->whereOr([$map1, $map2])->select();
- 闭包查询可以连缀,会自动加上括号,更清晰,如果是 OR,请用 whereOR();
$result = Db::name('user')->where(function ($query) {
$query->where('id', '>', 10);
})->whereOr(function ($query) {
$query->where('username', 'like', '%小%');
})->select();
- 对于比较复杂或你不知道如何拼装 SQL 条件,那么就直接使用 whereRaw()即可;
$result = Db::name('user')
->whereRaw('(username LIKE "%小%" AND email LIKE "%163%") OR (price > 80)')
->select();
- whereRaw()方式也支持参数绑定操作,具体如下;
$result = Db::name('user')
->whereRaw('(username LIKE :username AND email LIKE :email)
OR (price > :price)',
['username'=>'%小%', 'email'=>'%163%', 'price'=>80])
->select();
数据库的快捷查询
快捷查询
- 系统封装了很多
where
方法的快捷方式,之前学习了一些,全部如下:
whereColumn()
方法,比较两个字段的值,符合的就筛选出来;
$result = Db::name('user')
->whereColumn('update_time', '>=', 'create_time')
->select();
//相等可以简化,只需要两边的字段
// whereColumn('update_time', 'create_time')
- 系统还针对字段查询提供了几个方便查询的快捷方式;
whereFieldName()
方法,查询某个字段的值,注意FileName
是字段名;
Db::name('user')->whereEmail('xiaoxin@163.com')->find();
Db::name('user')->whereUsername('蜡笔小新')->find();
//如果字段是 create_time,则 whereCreateTime,驼峰式写法;
getByFieldName()
方法,查询某个字段的值,注意只能查询一条,不需要find()
;
Db::name('user')->getByEmail('xiaoxin@163.com');
getFieldByFieldName()
方法,通过查询得到某个指定字段的单一值;
Db::name('user')->getFieldByEmail('xiaoxin@163.com', 'username');
其它补充
- when()可以通过条件判断,执行闭包里的分支查询;
$result = Db::name('user')->when(false, function ($query) {
$query->where('id', '>', 0);
}, function ($query) {
$query->where('username', 'like', '%小%');
})->select();
数据库的事务和获取器
事务处理
- 数据库的表引擎需要是
InnoDB
才可以使用,如果不是调整即可; - 事务处理,需要执行多个SQL查询,数据是关联恒定的;
- 如果成功一条查询,改变了数据,而后一条失败,则前面的数据回滚;
- 比如:蜡笔小新给路飞3快钱,自己-3,对方+3,这时需要事务处理;
- 系统提供了两种事务处理的方式,第一种是自动处理,出错自动回滚;
Db::transaction(function () {
Db::name('user')->where('id', 19)->save(['price'=>Db::raw('price - 3')]);
Db::name('user1')->where('id', 20)->save(['price'=>Db::raw('price + 3')]);
});
- 手动处理,基本和原生处理类似,可以自行输出错误信息;
//启动事务
Db::startTrans();
try {
Db::name('user')->where('id', 19)->save(['price'=>Db::raw('price - 3')]);
Db::name('user1')->where('id', 20)->save(['price'=>Db::raw('price + 3')]);
//提交事务
Db::commit();
} catch (\Exception $e) {
echo '执行 SQL 失败!';
//回滚
Db::rollback();
}
获取器
- 获取器的意思就是:将数据的字段进行转换处理再进行操作;
- 比如在获取数据列表的时候,将获取到的邮箱字段全部大写;
$user = Db::name('user')->withAttr('email', function ($value, $data) {
return strtoupper($value);
})->select();
echo json($user);
数据库的数据集和代码提示
代码提示
- 一般来说,代码提示是通过注释来告知编辑器自动补全方法等;
- 对比一下,5.1的类库,发现6.x的类库没有写注释;
- 就拿Db类来说,只要把5.1的注释覆盖到6.x即可实现代码提示;
- 当然,是否精确,需要一一对比这些方法和参数,但绝大多数是相同的;
- 找到 Db 类,看它的注释:@see指向的是谁,是DbManager类;
- 然后将5.1的Db类注释,复制给DbManager类即可,以后其它的雷同操作;
数据集
- 所谓数据集,是当查询后的结果集,它是
think\Collection
类型和数组一样; - 虽然操作和数组类似,但它额外提供了一些方法,方法如下:
- 注意:这里的方法关键字某些和数据库查询类似,但它是数据集操作的方法;
- 由于方法较多,我们尝试几个理解一下即可,有需要可以回头查阅;
- 每种的典型,都拎出来说明了一下;
- 其它的方法,可以通过追逐方法查阅注释和参数来参考使用
最后一次更新于2020-07-23 15:05
0 条评论