thinkphp笔记-数据库高级查询、快捷查询

8592次阅读 546人点赞 作者: WuBin 发布时间: 2024-04-07 10:15:27
扫码到手机查看

高级查询

使用|(OR)或&(AND)来实现where 条件的高级查询,where 支持多个连缀;

$user = Db::name('user')
                    ->where('username|email', 'like', '%xiao%')
                    ->select();

上面这个对应的sql语句:SELECT * FROM `tp_user` WHERE ( `username` LIKE '%xiao%' OR `email` LIKE '%xiao%' )

所以username|email的意思就是username或者email里面含有xiao的行。

因为支持连缀,所以还可以再添加一个where

$user = Db::name('user')
                    ->where('username|email', 'like', '%xiao%')
                    ->where('price&uid', '>', 0)
                    ->select();

上面这个又添加了price和uid要大于0,对应的sql语句:SELECT * FROM `tp_user` WHERE ( `username` LIKE '%xiao%' OR `email` LIKE '%xiao%' ) AND ( `price` > '0' AND `uid` > 0 ),多一个where会自动加括号。

关联数组方式,可以在where 进行多个字段进行查询;

$user = Db::name('user')
                    ->where([
                        ['id', '>', 0],
                        ['status', '>=', 1],
                        ['price', '>=', 80],
                        ['email', 'like', '%xiao%']
                    ])
                    ->select();

对应生成的sql语句:SELECT * FROM `tp_user` WHERE `id` > 0 AND `status` >= 1 AND `price` >= '80' AND `email` LIKE '%xiao%'

因为只有一个where,所以没有添加括号。且多个数组条件是处于并列关系。

根据之前的课程中,条件字符串复杂组装,比如使用exp 了,就使用raw()方法;比如使用exp,

Db::name('user')
                    ->where([
                        ['id', '>', 0],
                        ['status', '>=', 1],
                        ['price', 'exp', ‘>=80’], // 这样写会有错误
                        ['email', 'like', '%xiao%']
                    ])
                    ->select();

正确写法应该是使用Db::raw(‘自定义的语句’)

Db::name('user')
                    ->where([
                        ['id', '>', 0],
                        ['status', '>=', 1],
                        ['price', 'exp', Db::raw('>=80')], // 正确
                        ['email', 'like', '%xiao%']
                    ])
                    ->select();

SELECT * FROM `tp_user` WHERE `id` > 0 AND `status` >= 1 AND ( `price` >=80 ) AND `email` LIKE '%xiao%'

如果有多个where,并且where 条件是分离的$map,而$map 本身有多个条件;

$map = [
                ['id', '>', 0],
                ['price', '>=', 80],
                ['email', 'like', '%xiao%']
];
$user = Db::name('user')->where($map)->select();

SELECT * FROM `tp_user` WHERE `id` > 0 AND `price` >= '80' AND `email` LIKE '%xiao%'

这时候如果再添加一个where,加上之前没有添加的status条件

$map = [
                ['id', '>', 0],
                ['price', '>=', 80],
                ['email', 'like', '%xiao%']
];
 $user = Db::name('user')
                    ->where($map)
                    ->where('status', 1)
                    ->select();

这时候返回的sql语句:SELECT * FROM `tp_user` WHERE `id` > 0 AND `price` >= '80' AND `email` LIKE '%xiao%' AND `status` = 1

这样的话是所有的条件都是平行的,email与status都处于平级关系,而我要的是$map的结果与status平级

$map = [
    ['id', '>', 0],
    ['price', '>=', 80],
    ['email', 'like', '%xiao%']
];
$user = Db::name('user')
        ->where([$map])
        ->where('status', 1)
        ->select();

SQL:SELECT * FROM `tp_user` WHERE ( `id` > 0 AND `price` >= '80' AND `email` LIKE '%xiao%' ) AND `status` = 1

用[$map],$map 条件如果需要先执行出结果,再和后续条件判断,也就是加上括号,那么,需要对这个$map 变量,再加上一个中括号处理优先级;

如果,条件中有多次出现一个字段,并且需要OR 来左右筛选,可以用whereOr;

$map1 = [
    ['username', 'like', '%小%'],
    ['email', 'like', '%163%']
];
$map2 = [
    ['username', 'like', '%孙%'],
    ['email', 'like', '%.com%']
];
$user = Db::name('user')
->where([$map1, $map2])
->select();

SELECT * FROM `tp_user` WHERE ( `username` LIKE '%小%' AND `email` LIKE '%163%' ) AND ( `username` LIKE '%孙%' AND `email` LIKE '%.com%' )

默认的where之间是用AND链接,如果需要使用OR链接,则改为whereOr

$user = Db::name('user')
->whereOr([$map1, $map2])
->select();

这时的sql语句:SELECT * FROM `tp_user` WHERE ( `username` LIKE '%小%' AND `email` LIKE '%163%' ) OR ( `username` LIKE '%孙%' AND `email` LIKE '%.com%' )

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

比如一个简单的闭包查询例子:

// 闭包查询 $query就是user对象
$user = Db::name('user')->where(function($query) {
    $query->where('id', '>', 0);
})->select();

所谓的闭包连缀,就是再闭包后面再跟一个where闭包

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

SQL:SELECT * FROM `tp_user` WHERE ( `id` > 0 ) AND ( `username` LIKE '%小%' )

如果闭包之间不想用AND,呢么直接使用whereOr即可。

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

SELECT * FROM `tp_user` WHERE ( `id` > 0 ) OR ( `username` LIKE '%小%' )

对于比较复杂或你不知道如何拼装SQL 条件,那么就直接使用whereRaw()即可;

$user = Db::name('user')
->whereRaw('(username LIKE "%小%" AND status = 1) OR id>0')
->select();

SELECT * FROM `tp_user` WHERE ( (username LIKE "%小%" AND status = 1) OR id>0 )

对于复杂的原生SQL语句查询,建议直接使用whereRaw

whereRaw()方式也支持参数绑定操作,与PDO的预处理配合使用。

$user = Db::name('user')
->whereRaw(
    '(username LIKE :username AND status = :status) OR id>:id',
    ['username' => '%小%', 'status' => 1, 'id'=>0]
)
->select();

SELECT * FROM `tp_user` WHERE ( (username LIKE "%小%" AND status = 1) OR id>0 )

最终结果的SQL语句与上面的一样,这里只是改为了参数绑定。

快捷查询

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

whereOr

字段OR查询

whereXor

字段XOR查询

whereNull查询字段是否为Null
whereNotNull

查询字段是否不为Nul1

whereIn

字段IN查询

whereNotIn

字段NOT IN查询

whereBetween

字段BETWEEN查询

whereNotBetween

字段NOT BETWEEN查询

whereLike

字段LIKE查询

whereNotLike

字段NOT LIKE查询

whereExists

EXISTS条件查询

whereNotExists

NOT EXISTS条件查询

whereExp

表达式查询

whereColumn

比较两个字段

whereColumn()方法,比较两个字段的值,符合的就筛选出来

// 找出update>=create的所有行
$user = Db::name('user')
           ->whereColumn('update_time', '>=', 'create_time')
            ->select();
 return json($user);

如果是等于,第二个参数传”=“,>whereColumn('update_time', '=', 'create_time')或者就不需要传递第二个参数了。

$user = Db::name('user')
            ->whereColumn('update_time', 'create_time')
            ->select();
return Db::getLastSql();

SELECT * FROM `tp_user` WHERE ( `update_time` = `create_time` ),这个主要用于对比出哪些用户的账号与email是相同的啊之类的查询。

系统还针对字段查询提供了几个方便查询的快捷方式

emailusernamecreate_timeupdate_time
xiaoxin@163.com蜡笔小新2016-06-27 16:45:262024-04-08 11:37:23

whereFieldName()方法,查询某个字段的值,注意FileName 是字段名,比如我要查询email=xiaoxin@163.com的行。

 $user = Db::name('user')->whereEmail('xiaoxin@163.com')->select();

如果不填参数

$user = Db::name('user')->whereEmail()->select();

SELECT * FROM `tp_user` WHERE `email` IS NULL,得到的结果就是空数组。

$user = Db::name('user')->whereUsername('蜡笔小新')->find();

这里要特别注意,因为字段名就是username,所以where+字段名(首字母要大写)= whereUsername,这里如果我改成:

$user = Db::name('user')->whereUserName('蜡笔小新')->find();

那么就会报错:Column not found: 1054 Unknown column 'user_name' in 'where clause'

所以,如果字段名中有下划线的,比如create_time,那么查询的时候使用驼峰式写法,即whereCreateTime:

 Db::name('user')->whereCreateTime('2016-06-27 16:45:26')->find();

getByFieldName()方法,查询某个字段的值,注意只能查询一条,不需要find();

 Db::name('user')->getByEmail('xiaoxin@163.com');

SELECT * FROM `tp_user` WHERE `email` = 'xiaoxin@163.com' LIMIT 1

这个方法只会查询到一条数据!

getFieldByFieldName()方法,通过查询得到某个指定字段的单一值,即通过一个字段找到另一个字段的值,而不是整条信息。也只返回1行。

getFieldBy固定+字段名(首字母大写)

// 第一个参数是要查找的字段内容,第二个参数是要显示的字段
// 这里是查找email字段=xiaoxin@163.com的行中的username字段的值
$user = Db::name('user')->getFieldByEmail('xiaoxin@163.com', 'username');

结果:只有字符串:蜡笔小新

SQL:SELECT `username` FROM `tp_user` WHERE `email` = 'xiaoxin@163.com' LIMIT 1

其他补充

when()可以通过条件判断,执行闭包里的分支查询,不是链式查询的那种合并。

$user = Db::name('user')->when(
    true,
    function($query) {
        $query->where('id', '>', 0);
    },
    function($query) {
        $query->where('username', 'like', '%小%');
    }
)->select();

 第一个参数是布尔值,决定执行第几个闭包,第一个参数是第一个匿名函数,第二个参数是第二个匿名函数。

如果第一个参数为true,那么执行第一个参数的匿名函数,如上例,执行语句如下:

SELECT * FROM `tp_user` WHERE `id` > 0

如果改为false:

Db::name('user')->when(
    false,
    function($query) {
        $query->where('id', '>', 0);
    },
    function($query) {
        $query->where('username', 'like', '%小%');
    }
)->select();

执行的SQL为:SELECT * FROM `tp_user` WHERE `username` LIKE '%小%',即为第二个匿名函数。

即在执行条件判断的时候,根据不同条件判断执行不同SQL的时候可以使用这个方法。力图减少代码中的If-else。

点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:thinkphp
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    10049次阅读 659人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    4677次阅读 346人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14754次阅读 967人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    13963次阅读 525人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    12705次阅读 1023人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    16943次阅读 1357人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    15465次阅读 1257人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    30556次阅读 2403人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    26529次阅读 2041人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录