数据库

参见《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 '数据查询发送异常!'
}

默认情况下,findselect方法返回的都是数组,区别在于后者是二维数组。

系统提供了一个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','thinkphp@qq.com')
->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']);

    第三个参数可以传入任何有效的时间表达式,会自动识别你的时间字段类型,支持的时间类型包括timestampsdatetimedateint

    区间查询 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 INEXISTS/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

ThinkPHP5.1学习笔记 数据库操作的更多相关文章

  1. JavaEE学习笔记---数据库操作篇

    测试JDBC和SQLServer的插入操作,源码如下: import java.sql.Connection;import java.sql.DriverManager;import java.sql ...

  2. MongoDB学习笔记——数据库操作

    使用use数据库名称来创建数据库,如果该数据库已经存在则返回这个数据库 语句格式:use DATABASE_NAME >use mynewdb switched to db mynewdb 使用 ...

  3. mysql学习笔记--数据库操作

    一.显示数据库 show databases; 二.创建数据库 create database [if not exists] 数据库名 [字符编码] 注意: a. 如果已经存在数据库再创建会报错 b ...

  4. MySQL学习笔记-数据库文件

    数据库文件 MySQL主要文件类型有如下几种 参数文件:my.cnf--MySQL实例启动的时候在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还介绍了参数类 ...

  5. MySQL学习笔记-数据库后台线程

    数据库后台线程 默认情况下讲述的InnoDB存储引擎,以后不再重复声明.后台线程有7个--4个IO thread,1个master thread,1个锁监控线程,1个错误监控线程.IO thread的 ...

  6. MongoDB学习笔记:Python 操作MongoDB

    MongoDB学习笔记:Python 操作MongoDB   Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...

  7. PHP学习之-数据库操作

    PHP学习之-数据库操作 1.PHP支持那些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Sybase,Db2,Or ...

  8. MySQL学习笔记-数据库内存

    数据库内存 InnoDB存储引擎内存由以下几个部分组成:缓冲池(buffer pool).重做日志缓冲池(redo log buffer)以及额外的内存池(additional memory pool ...

  9. Javascript学习笔记二——操作DOM

    Javascript学习笔记 DOM操作: 一.GetElementById() ID在HTML是唯一的,getElementById()可以定位唯一的一个DOM节点 二.querySelector( ...

随机推荐

  1. 2016女生专场 ABCDEF题解 其他待补...

    GHIJ待补... A.HUD5702:Solving Order Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3276 ...

  2. fastjson使用详解

    目录 二.fastjson使用 三.fastjson 常用 API 四.fastjson使用演示 测试类准备 1.java类转换为json字符串 2.json字符串转为java类 五.fastjson ...

  3. 利用 Hexo 或者 hugo 搭建个人博客

    我们无法选择生活的样子,但我们可以记下来. 博客的开始 其实,一切都是为了更好的装逼.好吧,我着相了. 最开始想做一个自己博客,主要是因为看到了很多人都有,觉得自己没有太 Low 了.于是申请了 CS ...

  4. JetBrains Pycharm破解,含破解文件和安装包2019.2版

    此教程支持最新的2019.3版本的Pycharm,并兼容之前的版本. 一.准备工作: 1.下载Pycharm 有条件的可以自行去官网下载,这里我提供了我下载的版本,已上传到百度网盘,链接在下方. 2. ...

  5. Spring Boot2 系列教程 (十八) | 整合 MongoDB

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 如题,今天介绍下 SpringBoot 是如何整合 MongoDB 的. MongoDB 简介 MongoDB 是由 C++ ...

  6. go slice与函数传值的理解

    go语言中所有的传值方式都是传值操作. 今天遇到了以下代码: func main(){ slice := make([],) fmt.Println(slice) change(s) fmt.Prin ...

  7. PowerDesigner配置Oracle数据库反向工程

    PowerDesigner配置Oracle数据库反向工程 作者:Jesai 贴吧:软件频道吧 1. 前言: PowerDesigner是Sybase的企业建模和设计解决方案,采用模型驱动方法,将业务与 ...

  8. Postman post csrf_token

    1.填入代码 var csrf_token = postman.getResponseCookie("csrftoken").value postman.clearGlobalVa ...

  9. 关于github显示不出来图片的问题

    今天打开github,突然发现图标图片等都显示不出来了. 控制台看了一下 百度查找了Failed to load resource: net::ERR_CERT_COMMON_NAME_INVALID ...

  10. 「 从0到1学习微服务SpringCloud 」11 补充篇 RabbitMq实现延迟消费和延迟重试

    Mq的使用中,延迟队列是很多业务都需要用到的,最近我也是刚在项目中用到,就在跟大家讲讲吧. 何为延迟队列? 延迟队列就是进入该队列的消息会被延迟消费的队列.而一般的队列,消息一旦入队了之后就会被消费者 ...