# 高級查詢
## 快捷查詢
快捷查詢方式是**一種多字段相同查詢條件**的簡化寫法,可以進一步簡化查詢條件的寫法,在多個字段之間用`|`分割表示`OR`查詢,用`&`分割表示`AND`查詢,可以實現下面的查詢,例如:
```
Db::table('think_user')
->where('name|title','like','thinkphp%')
->where('create_time&update_time','>',0)
->find();
```
生成的查詢SQL是:
```
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' OR `title` LIKE 'thinkphp%' ) AND ( `create_time` > 0 AND `update_time` > 0 ) LIMIT 1
```
> 快捷查詢支持所有的查詢表達式。
## 區間查詢
區間查詢是一種**同一字段多個查詢條件**的簡化寫法,例如:
```
Db::table('think_user')
->where('name', ['like', '%thinkphp%'], ['like', '%kancloud%'], 'or')
->where('id', ['>', 0], ['<>', 10], 'and')
->find();
```
生成的SQL語句為:
```
SELECT * FROM `think_user` WHERE ( `name` LIKE '%thinkphp%' OR `name` LIKE '%kancloud%' ) AND ( `id` > 0 AND `id` <> 10 ) LIMIT 1
```
> 區間查詢的查詢條件必須使用數組定義方式,支持所有的查詢表達式。
下面的查詢方式是錯誤的:
```
Db::table('think_user')
->where('name', ['like', 'thinkphp%'], ['like', '%thinkphp'])
->where('id', 5, ['<>', 10], 'or')
->find();
```
區間查詢其實可以用下面的方式替代,更容易理解,因為查詢構造器支持對同一個字段多次調用查詢條件,例如:
```
Db::table('think_user')
->where('name', 'like', '%think%')
->where('name', 'like', '%php%')
->where('id', 'in', [1, 5, 80, 50])
->where('id', '>', 10)
->find();
```
## 批量(字段)查詢
可以進行多個條件的批量條件查詢定義,例如:
```
Db::table('think_user')
->where([
['name', 'like', 'thinkphp%'],
['title', 'like', '%thinkphp'],
['id', '>', 0],
['status', '=', 1],
])
->select();
```
生成的SQL語句為:
```
SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 AND `status` = '1'
```
> 注意,`V5.1.7+`版本數組方式如果使用`exp`查詢的話,一定要用`raw`方法。
```
Db::table('think_user')
->where([
['name', 'like', 'thinkphp%'],
['title', 'like', '%thinkphp'],
['id', 'exp', Db::raw('>score')],
['status', '=', 1],
])
->select();
```
數組查詢方式,確保你的查詢數組不能被用戶提交數據控制,用戶提交的表單數據應該是作為查詢數組的一個元素傳入,如下:
```
Db::table('think_user')
->where([
['name', 'like', $name . '%'],
['title', 'like', '%' . $title],
['id', '>', $id],
['status', '=', $status],
])
->select();
```
> 注意,相同的字段的多次查詢條件可能會合并,如果希望某一個`where`方法里面的條件單獨處理,可以使用下面的方式,避免被其它條件影響。
```
$map = [
['name', 'like', 'thinkphp%'],
['title', 'like', '%thinkphp'],
['id', '>', 0],
];
Db::table('think_user')
->where([ $map ])
->where('status',1)
->select();
```
生成的SQL語句為:
```
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 ) AND `status` = '1'
```
如果使用下面的多個條件組合
```
$map1 = [
['name', 'like', 'thinkphp%'],
['title', 'like', '%thinkphp'],
];
$map2 = [
['name', 'like', 'kancloud%'],
['title', 'like', '%kancloud'],
];
Db::table('think_user')
->whereOr([ $map1, $map2 ])
->select();
```
生成的SQL語句為:
```
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' ) OR ( `name` LIKE 'kancloud%' AND `title` LIKE '%kancloud' )
```
> 善用多維數組查詢,可以很方便的拼裝出各種復雜的SQL語句
## 閉包查詢
```
$name = 'thinkphp';
$id = 10;
Db::table('think_user')->where(function ($query) use($name, $id) {
$query->where('name', $name)
->whereOr('id', '>', $id);
})->select();
```
生成的SQL語句為:
```
SELECT * FROM `think_user` WHERE ( `name` = 'thinkphp' OR `id` > 10 )
```
> 可見每個閉包條件兩邊也會自動加上括號,但需要注意,使用閉包查詢的時候不能使用`cache(true)`數據緩存,而應該使用指定key的方式例如`cache('key')`。
## 混合查詢
可以結合前面提到的所有方式進行混合查詢,例如:
```
Db::table('think_user')
->where('name', ['like', 'thinkphp%'], ['like', '%thinkphp'])
->where(function ($query) {
$query->where('id', ['<', 10], ['>', 100], 'or');
})
->select();
```
生成的SQL語句是:
```
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `name` LIKE '%thinkphp' ) AND ( `id` < 10 or `id` > 100 )
```
## 字符串條件查詢
對于一些實在復雜的查詢,也可以直接使用原生SQL語句進行查詢,例如:
```
Db::table('think_user')
->where('id > 0 AND name LIKE "thinkphp%"')
->select();
```
為了安全起見,我們可以對字符串查詢條件使用參數綁定,例如:
```
Db::table('think_user')
->where('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])
->select();
```
`V5.1.8+`版本開始,如果你要使用字符串條件查詢,推薦使用`whereRaw`方法。
```
Db::table('think_user')
->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])
->select();
```
## 使用Query對象查詢(`V5.1.5+`)
`V5.1.5+`版本開始,可以通過調用一次`where`方法傳入`Query`對象來進行查詢。
```
$query = new \think\db\Query;
$query->where('id','>',0)
->where('name','like','%thinkphp');
Db::table('think_user')
->where($query)
->select();
```
> Query對象的`where`方法僅能調用一次,如果`query`對象里面使用了非查詢條件的鏈式方法,則不會傳入當前查詢。
```
$query = new \think\db\Query;
$query->where('id','>',0)
->where('name','like','%thinkphp')
->order('id','desc') // 不會傳入后面的查詢
->field('name,id'); // 不會傳入后面的查詢
Db::table('think_user')
->where($query)
->where('title','like','thinkphp%') // 有效
->select();
```
## 快捷方法
系統封裝了一系列快捷方法,用于簡化查詢,包括:
方法作用`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`比較兩個字段下面舉例說明下兩個字段比較的查詢條件`whereColumn`方法的用法。
查詢`update_time`大于`create_time`的用戶數據
```
Db::table('think_user')
->whereColumn('update_time','>','create_time')
->select();
```
生成的SQL語句是:
```
SELECT * FROM `think_user` WHERE ( `update_time` > `create_time` )
```
查詢`name`和`nickname`相同的用戶數據
```
Db::table('think_user')
->whereColumn('name','=','nickname')
->select();
```
生成的SQL語句是:
```
SELECT * FROM `think_user` WHERE ( `name` = `nickname` )
```
相同字段條件也可以簡化為
```
Db::table('think_user')
->whereColumn('name','nickname')
->select();
```
`V5.1.11+`版本開始,支持數組方式比較多個字段
```
Db::name('user')->whereColumn([
['title', '=', 'name'],
['update_time', '>=', 'create_time'],
])->select();
```
生成的SQL語句是:
```
SELECT * FROM `think_user` WHERE ( `name` = `nickname` AND `update_time` > `create_time` )
```
## 動態查詢
查詢構造器還提供了兩個動態查詢機制,用于簡化查詢條件,包括`getBy`和`getFieldBy`。
動態查詢描述`whereFieldName`查詢某個字段的值`whereOrFieldName`查詢某個字段的值`getByFieldName`根據某個字段查詢`getFieldByFieldName`根據某個字段獲取某個值其中`FieldName`表示數據表的實際字段名稱的駝峰法表示,假設數據表`user`中有`email`和`nick_name`字段,我們可以這樣來查詢。
```
// 根據郵箱(email)查詢用戶信息
$user = Db::table('user')
->whereEmail('thinkphp@qq.com')
->find();
// 根據昵稱(nick_name)查詢用戶
$email = Db::table('user')
->whereNickName('like', '%流年%')
->select();
// 根據郵箱查詢用戶信息
$user = Db::table('user')
->getByEmail('thinkphp@qq.com');
// 根據昵稱(nick_name)查詢用戶信息
$user = Db::table('user')
->field('id,name,nick_name,email')
->getByNickName('流年');
// 根據郵箱查詢用戶的昵稱
$nickname = Db::table('user')
->getFieldByEmail('thinkphp@qq.com', 'nick_name');
// 根據昵稱(nick_name)查詢用戶郵箱
$email = Db::table('user')
->getFieldByNickName('流年', 'email');
```
> `getBy`和`getFieldBy`方法只會查詢一條記錄,可以和其它的鏈式方法搭配使用
## 條件查詢
5\.1的查詢構造器支持條件查詢,例如:
```
Db::name('user')->when($condition, function ($query) {
// 滿足條件后執行
$query->where('score', '>', 80)->limit(10);
})->select();
```
并且支持不滿足條件的分支查詢
```
Db::name('user')->when($condition, function ($query) {
// 滿足條件后執行
$query->where('score', '>', 80)->limit(10);
}, function ($query) {
// 不滿足條件執行
$query->where('score', '>', 60);
});
```
- 序言
- 基礎
- 安裝
- 開發規范
- 目錄結構
- 配置
- 架構
- 架構總覽
- 入口文件
- URL訪問
- 模塊設計
- 命名空間
- 容器和依賴注入
- Facade
- 鉤子和行為
- 中間件
- 路由
- 路由定義
- 變量規則
- 路由地址
- 閉包支持
- 路由參數
- 路由緩存
- 跨域請求
- 注解路由
- 路由分組
- MISS路由
- 資源路由
- 快捷路由
- 路由別名
- 路由綁定
- 域名路由
- URL生成
- 控制器
- 控制器定義
- 前置操作
- 跳轉和重定向
- 空操作和空控制器
- 分層控制器
- 資源控制器
- 請求
- 請求對象
- 請求信息
- 輸入變量
- 請求類型
- HTTP頭信息
- 偽靜態
- 參數綁定
- 請求緩存
- 響應
- 響應輸出
- 響應參數
- 重定向
- 數據庫
- 連接數據庫
- 查詢構造器
- 查詢數據
- 添加數據
- 更新數據
- 刪除數據
- 查詢表達式
- 鏈式操作
- 聚合查詢
- 時間查詢
- 高級查詢
- 視圖查詢
- JSON字段
- 子查詢
- 原生查詢
- 查詢事件
- 事務操作
- 監聽SQL
- 存儲過程
- 數據集
- 分布式數據庫
- 模型
- 定義
- 新增
- 更新
- 刪除
- 查詢
- JSON字段
- 獲取器
- 修改器
- 自動時間戳
- 只讀字段
- 軟刪除
- 類型轉換
- 數據完成
- 查詢范圍
- 模型輸出
- 模型事件
- 模型關聯
- 一對一關聯
- 一對多關聯
- 遠程一對多
- 多對多關聯
- 多態關聯
- 關聯預載入
- 關聯統計
- 關聯輸出
- 視圖
- 視圖渲染
- 視圖賦值
- 視圖過濾
- 模板引擎
- 模板
- 變量輸出
- 使用函數
- 運算符
- 原樣輸出
- 模板注釋
- 模板布局
- 模板繼承
- 包含文件
- 輸出替換
- 標簽庫
- 內置標簽
- 循環標簽
- 比較標簽
- 條件判斷
- 資源文件加載
- 標簽嵌套
- 原生PHP
- 定義標簽
- 標簽擴展
- 錯誤和日志
- 異常處理
- 日志處理
- 調試
- 調試模式
- Trace調試
- 性能調試
- SQL調試
- 變量調試
- 遠程調試
- 驗證
- 驗證器
- 驗證規則
- 錯誤信息
- 驗證場景
- 路由驗證
- 內置規則
- 獨立驗證
- 靜態調用
- 表單令牌
- 雜項
- 緩存
- Session
- Cookie
- 多語言
- 分頁
- 上傳
- 命令行
- 啟動內置服務器
- 自動生成目錄結構
- 創建類庫文件
- 生成類庫映射文件
- 清除緩存文件
- 生成配置緩存文件
- 生成數據表字段緩存
- 生成路由映射緩存
- 自定義指令
- 擴展庫
- 驗證碼
- 圖像處理
- Time
- 數據庫遷移工具
- Workerman
- MongoDb
- 單元測試
- 安全和性能
- 安全建議
- 優化建議
- 附錄
- 助手函數
- 升級指導
- 更新日志