数据库的时间查询

传统方式

  1. 可以使用>,<,>=,<=来筛选匹配时间的数据;
Db::name('user')->where('create_time', '>', '2018-1-1')->select();
  1. 可以使用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();

快捷方式

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

固定查询

  1. 使用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();
  1. 使用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();
  1. 使用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();

其它查询

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

聚合.原生.子查询

聚合查询

  1. 使用count方法,可以求出所查询数据的数量;
Db::name('user')->count();
  1. count()可设置指定id,比如有空值Nulluid,不会计算数量;
Db::name('user')->count('uid');
  1. 使用max方法,求出所查询数据字段的最大值;
Db::name('user')->max('price');
  1. 如果max方法,求出的值不是数值,则通过第二参数强制转换;
Db::name('user')->max('price', false);
  1. 使用min方法,求出所查询数据字段的最小值,也可以强制转换;
Db::name('user')->min('price');
  1. 使用avg方法,求出所查询数据字段的平均值;
Db::name('user')->avg('price');
  1. 使用sum方法,求出所查询数据字段的总和;
Db::name('user')->sum('price');

子查询

  1. 使用fetchSql方法,可以设置不执行SQL,而返回SQL语句,默认true;
Db::name('user')->fetchSql(true)->select();

QQ截图20200723090436.png

  1. 使用buildSql方法,也是返回SQL语句,不需要再执行select(),且有括号;
Db::name('user')->buildSql(true);

QQ截图20200723090554.png

  1. 结合以上方法,我们实现一个子查询;
$subQuery = Db::name('two')->field('uid')->where('gender','男')->buildSql(true);
$result = Db::name('one')->where('id','exp','IN '.$subQuery)->select();

QQ截图20200723090910.png

  1. 使用闭包的方式执行子查询;
$result = Db::name('one')->where('id', 'in', function ($query) {
    $query->name('two')->where('gender', '男')->field('uid');
})->select();

原生查询

  1. 使用query方法,进行原生SQL查询,适用于读取操作,SQL错误返回false;
Db::query('select * from tp_user');
  1. 使用execute方法,进行原生SQL更新写入等,SQL错误返回false;
Db::execute('update tp_user set username="孙悟空" where id=29');

链式查询方法

where

  1. 表达式查询,就是where()方法的基础查询方式;
Db::name('user')->where('id', '>', 70)->select();
  1. 关联数组查询,通过键值对来数组键值对匹配的查询方式;
$user = Db::name('user')->where([
'gender' => '男',
'price' => 100 ,
//'price' => [60,70,80],
])->select();
  1. 索引数组查询,通过数组里的数组拼装方式来查询;
$user = Db::name('user')->where([
['gender', '=', '男'],
['price', '=', '100']
])->select();
  1. 将复杂的数组组装后,通过变量传递,将增加可读性;
$map[] = ['gender', '=', '男'];
$map[] = ['price', 'in', [60, 70, 80]];
$user = Db::name('user')->where($map)->select();
  1. 字符串形式传递,简单粗暴的查询方式,whereRaw()支持复杂字符串格式;
Db::name('user')->whereRaw('gender="男" AND price IN (60, 70, 80)')->select();
  1. 如果SQL查询采用了预处理模式,比如id=:id,也能够支持;
Db::name('user')->whereRaw('id=:id', ['id'=>19])->select();

field

  1. 使用field方法,可以指定要查询的字段;
Db::name('user')->field('id, username, email')->select();
Db::name('user')->field(['id', 'username', 'email'])->select();
  1. 使用field方法,给指定的字段设置别名;
Db::name('user')->field('id,username as name')->select();
Db::name('user')->field(['id', 'username'=>'name'])->select();
  1. fieldRaw方法里,可以直接给字段设置MySQL函数;
Db::name('user')->fieldRaw('id,SUM(price)')->select();
  1. 使用field(true)的布尔参数,可以显式的查询获取所有字段,而不是*;
Db::name('user')->field(true)->select();

QQ截图20200723094751.png

  1. 使用withoutField方法中字段排除,可以屏蔽掉想要不显示的字段;
Db::name('user')->withoutField('details')->select();
  1. 使用field方法在新增时,验证字段的合法性;
Db::name('user')->field('username, email, details')->insert($data);

alias

  1. 使用alias方法,给数据库起一个别名;
Db::name('user')->alias('a')->select();

QQ截图20200723094914.png

limit

  1. 使用limit()方法,限制获取输出数据的个数;
Db::name('user')->limit(5)->select();
  1. 分页模式,即传递两个参数,比如从第3条开始显示5条limit(2,5);
Db::name('user')->limit(2, 5)->select();
  1. 实现分页,需要严格计算每页显示的条数,然后从第几条开始;
//第一页
Db::name('user')->limit(0, 5)->select();
//第二页
Db::name('user')->limit(5, 5)->select();

QQ截图20200723104545.png

page

  1. page()分页方法,优化了limit()方法,无须计算分页条数;
//第一页
Db::name('user')->page(1, 5)->select();
//第二页
Db::name('user')->page(2, 5)->select();

QQ截图20200723104617.png

order

  1. 使用order()方法,可以指定排序方式,没有指定第二参数,默认asc;
Db::name('user')->order('id', 'desc')->select();
  1. 支持数组的方式,对多个字段进行排序;
Db::name('user')->order(['create_time'=>'desc', 'price'=>'asc'])->select();
  1. 使用orderRaw()方法,支持排序的时候指定MySQL函数;
Db::name('user')->orderRaw('FIELD(username,"樱桃小丸子") DESC')->select();

QQ截图20200723104806.png

group

  1. 使用group()方法,给性别不同的人进行price字段的总和统计;
Db::name('user')->fieldRaw('gender, SUM(price)')->group('gender')->select();

QQ截图20200723104852.png

  1. 也可以进行多字段分组统计;
Db::name('user')->fieldRaw('gender, SUM(price)')->group('gender,password')->select();

QQ截图20200723104921.png

having

  1. 使用group()分组之后,再使用having()进行筛选;
$result = Db::name('user')
->fieldRaw('gender, SUM(price)')
->group('gender')
->having('SUM(price)>600')
->select();

QQ截图20200723105008.png

数据库的高级查询

高级查询

  1. 使用|(OR)&(AND)来实现where条件的高级查询,where支持多个连缀;
$result = Db::name('user')
->where('username|email', 'like', '%xiao%')
->where('price&uid', '>', 0)
->select();

QQ截图20200723140040.png

  1. 关联数组方式,可以在where进行多个字段进行查询;
$result = Db::name('user')->where([
['id', '>', 0],
['status', '=', 1],
['price', '>=', 80],
['email', 'like', '%163%']
])->select();

QQ截图20200723140342.png

  1. 根据之前的课程中,条件字符串复杂组装,比如使用exp了,就使用raw()方法;
$result = Db::name('user')->where([
['status', '=', 1],
['price', 'exp', Db::raw('>80')]
])->select();

QQ截图20200723140415.png

  1. 如果有多个where,并且where条件是分离的$map,而$map本身有多个条件;
  2. 那么$map条件如果需要先执行出结果,再和后续条件判断,也就是加上括号;
  3. 那么,需要对这个$map变量,再加上一个中括号处理优先级;
$map = [
['status', '=', 1],
['price', 'exp', Db::raw('>80')]
];
$result = Db::name('user')
->where([$map])
->where('status', '=', '%163.com%')->select();

QQ截图20200723140514.png

  1. 如果,条件中有多次出现一个字段,并且需要 OR 来左右筛选,可以用 whereOr;
$map1 = [
['username', 'like', '%小%'],
['email', 'like', '%163%']
];
$map2 = [
['username', 'like', '%孙%'],
['email', 'like', '%.com%']
];
$result = Db::name('user')->whereOr([$map1, $map2])->select();

QQ截图20200723140813.png

  1. 闭包查询可以连缀,会自动加上括号,更清晰,如果是 OR,请用 whereOR();
$result = Db::name('user')->where(function ($query) {
$query->where('id', '>', 10);
})->whereOr(function ($query) {
$query->where('username', 'like', '%小%');
})->select();

QQ截图20200723140936.png

  1. 对于比较复杂或你不知道如何拼装 SQL 条件,那么就直接使用 whereRaw()即可;
$result = Db::name('user')
->whereRaw('(username LIKE "%小%" AND email LIKE "%163%") OR (price > 80)')
->select();

QQ截图20200723141036.png

  1. whereRaw()方式也支持参数绑定操作,具体如下;
$result = Db::name('user')
->whereRaw('(username LIKE :username AND email LIKE :email)
OR (price > :price)',
['username'=>'%小%', 'email'=>'%163%', 'price'=>80])
->select();

QQ截图20200723141119.png

数据库的快捷查询

快捷查询

  1. 系统封装了很多where方法的快捷方式,之前学习了一些,全部如下:

QQ截图20200723141351.png

  1. whereColumn()方法,比较两个字段的值,符合的就筛选出来;
$result = Db::name('user')
->whereColumn('update_time', '>=', 'create_time')
->select();
//相等可以简化,只需要两边的字段
// whereColumn('update_time', 'create_time')

QQ截图20200723141751.png

  1. 系统还针对字段查询提供了几个方便查询的快捷方式;
  2. whereFieldName()方法,查询某个字段的值,注意FileName是字段名;
Db::name('user')->whereEmail('xiaoxin@163.com')->find();
Db::name('user')->whereUsername('蜡笔小新')->find();
//如果字段是 create_time,则 whereCreateTime,驼峰式写法;

QQ截图20200723141955.png

  1. getByFieldName()方法,查询某个字段的值,注意只能查询一条,不需要find();
Db::name('user')->getByEmail('xiaoxin@163.com');

QQ截图20200723142030.png

  1. getFieldByFieldName()方法,通过查询得到某个指定字段的单一值;
Db::name('user')->getFieldByEmail('xiaoxin@163.com', 'username');

QQ截图20200723142157.png

其它补充

  1. when()可以通过条件判断,执行闭包里的分支查询;
$result = Db::name('user')->when(false, function ($query) {
$query->where('id', '>', 0);
}, function ($query) {
$query->where('username', 'like', '%小%');
})->select();

QQ截图20200723142253.png

数据库的事务和获取器

事务处理

  1. 数据库的表引擎需要是InnoDB才可以使用,如果不是调整即可;
  2. 事务处理,需要执行多个SQL查询,数据是关联恒定的;
  3. 如果成功一条查询,改变了数据,而后一条失败,则前面的数据回滚;
  4. 比如:蜡笔小新给路飞3快钱,自己-3,对方+3,这时需要事务处理;
  5. 系统提供了两种事务处理的方式,第一种是自动处理,出错自动回滚;
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')]);
});
  1. 手动处理,基本和原生处理类似,可以自行输出错误信息;
//启动事务
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();
}

获取器

  1. 获取器的意思就是:将数据的字段进行转换处理再进行操作;
  2. 比如在获取数据列表的时候,将获取到的邮箱字段全部大写;
$user = Db::name('user')->withAttr('email', function ($value, $data) {
    return strtoupper($value);
})->select();
echo json($user);

QQ截图20200723142925.png

数据库的数据集和代码提示

代码提示

  1. 一般来说,代码提示是通过注释来告知编辑器自动补全方法等;
  2. 对比一下,5.1的类库,发现6.x的类库没有写注释;
  3. 就拿Db类来说,只要把5.1的注释覆盖到6.x即可实现代码提示;
  4. 当然,是否精确,需要一一对比这些方法和参数,但绝大多数是相同的;
  5. 找到 Db 类,看它的注释:@see指向的是谁,是DbManager类;
  6. 然后将5.1的Db类注释,复制给DbManager类即可,以后其它的雷同操作;

数据集

  1. 所谓数据集,是当查询后的结果集,它是think\Collection类型和数组一样;
  2. 虽然操作和数组类似,但它额外提供了一些方法,方法如下:

QQ截图20200723143203.png

QQ截图20200723143211.png

  1. 注意:这里的方法关键字某些和数据库查询类似,但它是数据集操作的方法;
  2. 由于方法较多,我们尝试几个理解一下即可,有需要可以回头查阅;

QQ截图20200723150052.png

  1. 每种的典型,都拎出来说明了一下;
  2. 其它的方法,可以通过追逐方法查阅注释和参数来参考使用