ThinkPHP6.0学习笔记-数据库操作

ThinkPHP数据库操作

Mirror王宇阳
建议参考官方文档

数据库配置文件

config\database.php是thinkphp的数据库配置文件,在开发环境中该数据库文件主要是根据.Env文件,迁入到生产环境后.Env需要被忽略。

default配置用于设置默认使用的数据库连接配置。
connections配置具体的数据库连接信息,default配置参数定义的连接配置必须要存在。

创建数据库连接

namespace app\controller;
use think\facade\Db;

class DataTest
{
    public function index()
    {
        $user = Db::table('tp_user')->select();
        return json($user);
    }
}

数据库操作

Db是thinkphp封装的数据库操作方法,调用需要use think\facade\Db

Db::getLastSql():返回最近一次的sql执行语句

数据查询

find()方法:查询表中单个数据,存在则返回否则返回null

# 查询tp_user数据表中的单个数据
return json(
    Db::table('tp_user')// 如何设置了表前缀可以忽略tp_
    	->where('id',20)
    	->find()
);
# select * from `tp_user` where `id` = 20 limit 1

findOrEmpty()方法:不存在数据返回空数组,不返回null

findOrFail()方法:不存在抛出DataNotFoundException异常


select()方法:查询表中多个数据,存在返回否则返回null

return json(
    Db::table('tp_user')
    	->select()
);

toArray()方法:将select()返回的数据集对象转为数组

在不使用json时,select()返回的只是一个数据集对象,json转换了对象为json

selectOrFail():不存在抛出DataNotFoundException异常

find()select()是最终的输出,在输出前可以使用各式各样的链式操作


指定列column()/值value()查询

  • 指定查询某一列的数据内容

    return json(
        Db::table('tp_user')
        	->column('username')
    );
    
  • 指定查询某一值(通过条件约束查询字段值)

    return json(
        Db::table('tp_user')
        	->where('username','路飞')
        	->value('password')
        // 查询(username)路飞的密码(password)
    );
    

数据分批处理: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访问处理大量数据,很容易导致超时。


游标查询cursor()

利用文件PHP生成器特性,每次查询只读取一行,然后再读取速度时自动定位到下一行继续读取

$cursor = Db::table('tp_user')->cursor();
foreach($cursor as $user){
	dump($user);
    // dump():thinkphp自带的一种打印调试函数
}

相关补充

使用->将多种查询方法、条件进行链式组合;

Db::table('tp_user')返回的是查询对象Q;当一个查询对象第二次查询会保留第一次查询值或条件,可以使用removeOption()方法清除查询对象缓存的查询条件和值


数据添加

insert():添加一条数据,成功添加返回'1'

$data = [
    'username'  =>  '柯南',
    'password'  =>  '0504',
    'gender'    =>  '男',
    'email'     =>  '[email protected]',
    'price'     =>   10,
    'details'   =>  '112',
];
return json(Db::table('tp_user')->insert($data));

如果添加的字段与数据表中的字段不符合,系统会抛出异常;强行添加不存在的字段数据可以使用strick(false)忽略异常信息

replace():【仅支持mysql数据库】

会修改有错误的字段名

insertGetId():添加成功返回新增数据的主键ID


insertAll():添加多条数据,返回成功添加的数据条数

public function index()
{
    $data = [
        [
            'username'  =>  '柯南',
            'password'  =>  '0504',
            'gender'    =>  '男',
            'email'     =>  '[email protected]',
            'price'     =>   10,
            'details'   =>  '112',
        ],
        [
            'username'  =>  '小哀',
            'password'  =>  '1214',
            'gender'    =>  '女',
            'email'     =>  '[email protected]',
            'price'     =>   10,
            'details'   =>  '192',
        ],
        [
            'username'  =>  '小兰',
            'password'  =>  '3344',
            'gender'    =>  '女',
            'email'     =>  '[email protected]',
            'price'     =>   18,
            'details'   =>  '202',
        ],
    ];
    return Db::table('tp_user')->insertAll($data);
}

save():通用的写入方法,可以自动的判断当前的数据操作是添加或者修改(更新);通过判断是否存在主键判断。


数据修改(更新)

updata():修改数据,返回成功修改的行数否则返回0

$data = [
    'username'  =>  '琴酒',
];
Db::table('tp_user')
    ->where('id',302)
    ->update($data);
return Db::getLastSql();
// UPDATE `tp_user` SET `username` = '琴酒' WHERE `id` = 302

在更新的数据$data中添加主键id,可以省略掉where()

$data = [
    'id'		=>	 302 ,
    'username'  =>  '琴酒',
];
Db::table('tp_user')
    ->update($data);
return Db::getLastSql();

使用save()方法也可以更新带有主键ID的数据

$data = [
    'id'		=>   302 ,
    'username'  =>  '琴酒',
];
Db::table('tp_user')
    ->save($data);
return Db::getLastSql();

支持使用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')
    ]);

raw()

raw的单词原义是“原生”,也就是Db::raw(***)中的字符串会被认为原生的sql语义


自增inc()/自减dec()

// 默认步长为'1'
inc('字段名','步长');
dec('字段名','步长');
Db::table('tp_user')
    ->where('id',302)
    ->inc('price',5)
	->update();
Db::table('tp_user')
    ->where('id',302)
    ->dec('price',10)
    ->update();


数据删除

delete():数据删除

// 通过主键ID删除数据
Db::table('tp_user')->delete(306);
// 支持数组
Db::table('tp_user')->delete([306,307,308]);
// 通过where条件删除
Db::table('tp_user')->where('id',307)->delete();
// 删除所有数据(清空数据表)
Db::table('tp_user')->delete(true);

在业务数据中使用软删除(将数据的ID标记删除,使用新的内容覆盖ID标记)


查询表达式

比较查询
where('字段名','[表达式]','查询条件');

where()有三个参数值,第二个参数可忽略(普通表达式有:> < = <> <= >= ),参数空缺是默认为= ,支持数组传递和字符串传递;第三个参数查询条件支持数组传递条件值;第四个参数是基于第三个参数采用数组传递条件值,使用或与非来决定多个条件之间的逻辑关系


区间查询

like()/not like() 根据指定的模糊条件查询匹配

  • 模糊查询

    Db::table('tp_user')
        ->where('email','like','xiao%')
        ->select()
    //====================================//
    Db::table('tp_user')
        // 多个查询条件,数组传递
        ->where('email','like',['xiao%','ke%'],'OR')
        //whereOr('email','like',['xiao%','ke%'])
        ->select()
    

    %:模糊匹配多个字符

    *:模糊匹配单个字符

    快捷方法=>whereLink()/whereNoLink()

Db::table('tp_user')
    ->whereLike('email','xiao%')
    ->select()
//=============================//
Db::table('tp_user')
    ->whereNotLike('email','xiao%')
    ->select()

between()/not between()查询条件支持的字符串或数组,指定查询一个范围内的数据,接收两个参数一个起始点另一个终止点。

Db::table('tp_user')
    ->where('id','between','301,304')
    // 同时也支持数组传递
    ->select()

等效于

SELECT * FROM `tp_user` WHERE `id` BETWEEN 301 AND 304

快捷方式:whereBetween()/whereNotBetween()


in()/not in()查询条件支持的字符串或数组,精确指定查询的位置。

Db::table('tp_user')
    ->where('id','in','301,302,303')
    // 同时也支持数组传递
    ->select()

等效于

SELECT * FROM`tp_user` WHERE`id` IN(301,302,303)

快捷方式:whereIn()/whereNotIn()


Null()/not Null():判断字段是否为空

快捷方式:whereNull()/whereNotNull()


exp:表达式

exp支持复杂的查询表达式构造

Db::table('tp_user')
    ->where('id','in','301,302,303')
    ->select();
Db::table('tp_user')
    ->where('id','exp','IN (301,302,303)')
    ->select();

exp查询的条件不会被当成字符串,会被视为一个查询表达式,支持sql语法的函数和字段

快捷方式:whereExp()


时间查询

  • 传统方式:

    where()基本表达式可以进行基本时间查询

    Db::table('tp_user')
        ->where('create_time','>','2018-01-01')
        ->select();
    
    SELECT * FROM `tp_user` WHERE `create_time` > '2018-01-01'
    

    between()设置时间查询的区间

    Db::table('tp_user')
        ->where('create_time','between','2018-01-01,2020-01-01')
        ->select();
    
    SELECT * FROM `tp_user` WHERE `create_time` BETWEEN '2018-01-01' AND 2020-01-01'
    
  • 快捷查询:

    whereTime()可以直接使用普通表达式符号

    Db::table('tp_user')
        ->whereTime('create_time','>','2018-01-01')
        ->select();
    

    whereBetweenTime()/whereNotBetweenTime()区间查询时间

    Db::table('tp_user')
        ->whereBetweenTime('create_time','2018-01-01,2020-01-01')
        ->select();
    
  • 固定查询:

    whereyear():查询当年默认|去年last year|其他年份20xx的数据

    $data=Db::table('tp_user')
         ->whereYear('create_time')
         ->select();
    
    SELECT * FROM `tp_user` WHERE `create_time` BETWEEN '2020-01-01 00:00:00' AND '2020-12-31 23:59:59'
    
    $data=Db::table('tp_user')
         ->whereYear('create_time','last year')
         ->select();
    
    SELECT * FROM `tp_user` WHERE `create_time` BETWEEN '2019-01-01 0:00:00' AND '2019-12-31 23:59:59'
    
    $data=Db::table('tp_user')
         ->whereYear('create_time','2018')
         ->select();
    
    SELECT * FROM `tp_user` WHERE `create_time` BETWEEN '2018-01-01 0:00:00' AND '2018-12-31 23:59:59'
    
  • whereMonth()查询当月、上月last month、指定月份(2020-01)

  • whereWeek()查询本周、上周、指定周(以2020-01-01开始的七天)

  • whereDay()查询今天、昨天last Day、指定日期(2020-01-01)

  • 精准时间查询(时分秒)

    查询指定的时间段

    Db::table('tp_user')
    ->whereBetweenTimeField('start_time','end_time')
    ->select();
    

    配置database.php中的time_query_rule自定义时间查询规则

时间查询的更多方法建议参考官方文档


聚合查询

count():返回所查询数据的数量(可以指定字段,不统计null内容)

Db:table('tp_user')->count();
Db:table('tp_user')->count('delete_time');
SELECT COUNT(`delete_time`) AS think_count FROM `tp_user`

max()/min():返回最大/最小值必须指定字段名

$data=Db::table('tp_user')->max('price');
$data=Db::table('tp_user')->min('price');

avg()/sum():返回平均值/总和值必须指定字段名

$data=Db::table('tp_user')->avg('price');
$data=Db::table('tp_user')->sum('price');

子查询

fetchSql():参数设置是否执行(true|false),默认true不执行sql,而是返回sql语句(默认返回sql语句,不执行sql)且需要执行select()

// 只返回SQL语句,不执行sql操作
Db::table('tp_user')->fetchSql(true)->select();
// 执行sql操作,不返回SQL语句
Db::table('tp_user')->fetchSql(false)->select();

buildSql():返回SQL语句且不执行操作,不用执行select()

// 返回SQL语句,并在sql语句两端添加圆括号
Db::table('tp_user')->buildSql(true);
// 返回SQL语句,不添加圆括号
Db::table('tp_user')->buildSql(false);
$subQuery = Db::table('tp_two')
    ->field('uid')
    ->where('gender','男')
    ->buildSql(true);

$data = Db::table('tp_one')
    ->whereExp('id','IN'.$subQuery)
    ->select();
SELECT * FROM `tp_one` WHERE ( `id` IN( SELECT `uid` FROM `tp_two` HERE `gender` = '男' ) )

闭包构造子查询

Db::table('tp_one')
    ->where('id','IN', function($query){
        $query->table('tp_two')
            ->where('gender','男')
            ->field('uid');
      })->select();
SELECT * FROM`tp_one` WHERE`id` IN(SELECT`uid` FROM`tp_two` HERE`gender` ='男')

原生查询

query()进行原生SQL查询,适用于读取操作

Db::query('select * from tp_user');

execute()进行原生SQL更新写入

Db::execute('update tp_user set username="柯南" where id=308');

链式操作

建议参考官方文档的介绍,比较详细

连贯操作 作用 支持的参数类型
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 用于查询缓存 支持多个参数
with* 用于关联预载入 字符串、数组
bind* 用于数据绑定操作 数组或多个参数
comment 用于SQL注释 字符串
force 用于数据集的强制索引 字符串
master 用于设置主服务器读取数据 布尔值
strict 用于设置是否严格检测字段名是否存在 布尔值
sequence 用于设置Pgsql的自增序列名 字符串
failException 用于设置没有查询到数据是否抛出异常 布尔值
partition 用于设置分区信息 数组 字符串
replace 用于设置使用REPLACE方式写入 布尔值
extra 用于设置额外查询规则 字符串
duplicate 用于设置DUPLCATE信息 数组
where

前面接触的where方法足够了,这里着重的写“数组条件”

关联数组:等值于AND条件

Db::table('tp_user')->where(
    [
        'gender'	=>	'男',
        'uid'		=>	 Null,
    ])->select();
SELECT * FROM `tp_user` WHERE `gender` = '男' AND `uid` IS NULL

索引数组:设置多个AND查询条件

Db::table('tp_user')->where([
    	['create_time','>','2018'],
    	['gender','=','男']
	])->select();
SELECT * FROM `tp_user` WHERE `create_time` > '2018' AND `gender` = 男'

数组条件也可以提前设置;where中直接引用即可

使用| (OR) & (AND) :(支持多个where,属于AND连接)

Db::table('tp_user')
    ->where("username|email",'like','%xiao%')
    ->where('price&uid','>',0)
    ->select();
SELECT * FROM `tp_user` WHERE ( `username` LIKE '%xiao%' OR `email` LIKE '%xiao%' ) AND ( `price` > 0 AND `uid` > 0 )

数组方式如果使用exp查询的话,一定要用raw方法。

Db::table('think_user')
    ->where([
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', 'exp', Db::raw('>score')],
        ['status', '=', 1],
    ])
    ->select();

闭包查询可以连缀,会自动加上括号,更清晰,如果是 OR,请用 whereOR();

$user = Db::name('user')
    ->where(function ($query) { 
        $query->where('id', '>', 10); })
    ->whereOr(function ($query) { 
        $query->where('username', 'like', '%小%'); 
    })->select();
****
field

field()标识需要返回和操作的字段,可以(采用字符串或数组传递参数)指定一个或多个字段名(select()不可以使用)

withoutField()排除指定的字段名,输出其他字段名

fieldRaw()可以在选定字段操作的同时也可以对字段设置sql函数(例如:um(),avg(),count()……)

官方文档:用于写入

field()在数据库写入的时候,可以指定对特点的字段进行写入操作,这样一来就会制约变动哪些字段(合法字段验证:文档中说可以校验字段的正确性)


limit

limit指定查询和操作的数量(分页)

例如获取满足要求的10个用户,如下调用即可:

Db::table('user')
    ->where('status',1)
    ->field('id,name')
    ->limit(10)
    ->select();

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

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

如果用于insertAll方法的话,则可以分批多次写入,每次最多写入limit方法指定的数

Db::table('user')
->limit(100)
->insertAll($userList);
Db::table('article')->limit(10,25)->select();

表示查询文章数据,从第10行开始的25条数据(可能还取决于where条件和order排序的影响 这个暂且不提)。

对于大数据表,尽量使用limit限制查询结果,否则会导致很大的内存开销和性能问题。


page

主要应用在分页查询

Db::table('tp_user')->limit(0,10)->select();
Db::table('tp_user')->limit(10,10)->select();
Db::table('tp_user')->page(1,10)->select();
Db::table('tp_user')->page(2,10)->select();

page()的便利之处显而易见,不需要计算第二页的起始页,系统自动计算。

Db::table('tp_user')->limit(10)->page(1)->select();

order

对操作的结果进行排序

Db::table('user')
    ->where('status', 1)
    ->order('id', 'desc')
    ->limit(5)
	->select();

desc 降序 | asc 升序

支持使用数组对多个字段排序

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

group

sql的常用函数,适用分组合计,对一个或多个列的结果集进行分组;接收一个参数(仅字符串)支持多字段分组

Db::table('tp_user')
    ->fieldRaw('gender,count(username)')
    ->group('gender')
    ->select();
having

配合group的结果从分组总筛选数据(聚合条件)

Db::table('tp_user')
    ->fieldRaw('gender,count(username)')
    ->group('gender')
    ->having('sum(price)>600')
    ->select();
****
table

table用于操作指定的数据表


alias

alias设置当前数据表的别名

Db::table('tp_user')
    ->alias('user')
    ->select()
SELECT * FROM `tp_user` `user`

strict

strict()设置是否严格检查字段名

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

系统默认值是由数据库配置参数fields_strict决定,因此修改数据库配置参数可以进行全局严格检查配置,如下:

// 关闭严格检查字段是否存在
'fields_strict'  => false

快捷查询

方法 作用
whereOr 字段OR查询
whereXor 字段XOR查询
whereNull 查询字段是否为Null
whereNotNull 查询字段是否不为Null
whereIn 字段IN查询
whereNotIn 字段NOT IN查询
whereBetween 字段BETWEEN查询
whereNotBetween 字段NOT BETWEEN查询
whereLike 字段LIKE查询
whereNotLike 字段NOT LIKE查询
whereExists EXISTS条件查询
whereNotExists NOT EXISTS条件查询
whereExp 表达式查询
whereColumn 比较两个字段
动态查询 描述
whereFieldName 查询某个字段的值
whereOrFieldName 查询某个字段的值
getByFieldName 根据某个字段查询
getFieldByFieldName 根据某个字段获取某个值

数据库事务处理

需要表引擎为InnoDB

transaction()事务处理:自动处理,出错则自动回滚

Db::transaction(function() {
    Db::table('tp_user')
        ->where('id',19)
        ->save(['price'=>Db::raw('price-3')]);
    Db::table('tp_user')
        ->where('id',20)
        ->save(['price'=>Db::raw('price + 3')]);
});

seartTrans()事务处理:手动处理,可以自行输出错误信息

Db::startTrans();//启动事务处理
try{
    Db::table('tp_user')
        ->where('id',19)
        ->save(['price'=>Db::raw('price - 3')]);
    Db::table('tp_user')
        ->where('id',20)
        ->save(['price'=>Db::raw('price + 3')]);
    
    Db::commit();//提交事务(执行)
} catch (\Exception $e){
    echo "error".$e;
    // 回滚事务
    Db::rollback();
}

获取器

将数据的字段进行转换处理在进行操作

withAttr() 传入两个参数(当前字段的值和所有的数据)

$user =  Db::table('tp_user')
    ->withAttr('email',function($value , $data){
        return strtoupper($value);
    })->select();
return Db::getLastSql() . "<hr>" . $user;

数据集

数据集就是查询后的结果集

// 获取数据集
$users = Db::name('user')->select();
// 遍历数据集
foreach($users as $user){
    echo $user['name'];
    echo $user['id'];
}

Collection类包含了下列主要方法:

方法 描述
isEmpty 是否为空
toArray 转换为数组
all 所有数据
merge 合并其它数据
diff 比较数组,返回差集
flip 交换数据中的键和值
intersect 比较数组,返回交集
keys 返回数据中的所有键名
pop 删除数据中的最后一个元素
shift 删除数据中的第一个元素
unshift 在数据开头插入一个元素
push 在结尾插入一个元素
reduce 通过使用用户自定义函数,以字符串返回数组
reverse 数据倒序重排
chunk 数据分隔为多个数据块
each 给数据的每个元素执行回调
filter 用回调函数过滤数据中的元素
column 返回数据中的指定列
sort 对数据排序
order 指定字段排序
shuffle 将数据打乱
slice 截取数据中的一部分
map 用回调函数处理数组中的元素
where 根据字段条件过滤数组中的元素
whereLike Like查询过滤元素
whereNotLike Not Like过滤元素
whereIn IN查询过滤数组中的元素
whereNotIn Not IN查询过滤数组中的元素
whereBetween Between查询过滤数组中的元素
whereNotBetween Not Between查询过滤数组中的元素

猜你喜欢

转载自www.cnblogs.com/wangyuyang1016/p/12681744.html