亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

ディレクトリ 検索
閱讀前篇 簡(jiǎn)介 Yii 是什么 從 Yii 1.1 升級(jí) 入門 安裝 Yii 運(yùn)行應(yīng)用 第一次問候 使用Forms 數(shù)據(jù)庫(kù)應(yīng)用 使用 Gii 生成代碼 進(jìn)階 應(yīng)用結(jié)構(gòu) 概述 入口腳本 應(yīng)用(Applications) 應(yīng)用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴(kuò)展(Extensions) 請(qǐng)求處理 運(yùn)行概述 啟動(dòng)引導(dǎo)(Bootstrapping) 路由和創(chuàng)建URL 請(qǐng)求(Requests) 響應(yīng)(Responses) Sessions 和 Cookies 錯(cuò)誤處理(Handling Errors) 日志(Logging) 關(guān)鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類自動(dòng)加載(Autoloading) 服務(wù)定位器(Service Locator) 依賴注入容器(Dependency Injection Container) 配合數(shù)據(jù)庫(kù)工作 數(shù)據(jù)庫(kù)訪問 (Data Access Objects) 查詢生成器(Query Builder) 活動(dòng)記錄(Active Record) 數(shù)據(jù)庫(kù)遷移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用戶數(shù)據(jù) 創(chuàng)建表單(Creating Forms) 輸入驗(yàn)證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復(fù)合表單(Getting Data for Multiple Models) 顯示數(shù)據(jù) 格式化輸出數(shù)據(jù)(Data Formatting) 分頁(yè)(Pagination) 排序(Sorting) 數(shù)據(jù)提供器(Data Providers) 數(shù)據(jù)小部件(Data Widgets) 客戶端腳本使用(Working with Client Scripts) 主題(Theming) 安全 認(rèn)證(Authentication) 授權(quán)(Authorization) 處理密碼(Working with Passwords) 客戶端認(rèn)證(Auth Clients) 最佳安全實(shí)踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁(yè)面緩存 HTTP 緩存 RESTfull Web服務(wù) 快速入門(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(yīng)(Response Formatting) 授權(quán)認(rèn)證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯(cuò)誤處理(Error Handling) 開發(fā)工具 調(diào)試工具欄和調(diào)試器 使用Gii生成代碼 生成API文檔 測(cè)試 概述(Overview) 配置測(cè)試環(huán)境(Testing environment setup) 單元測(cè)試(Unit Tests) 功能測(cè)試(Function Tests) 驗(yàn)收測(cè)試(Acceptance Tests) 測(cè)試夾具(Fixtures) 高級(jí)專題 高級(jí)應(yīng)用模板 創(chuàng)建自定義應(yīng)用程序結(jié)構(gòu) 控制臺(tái)命令 核心驗(yàn)證器(Core Validators) 國(guó)際化 收發(fā)郵件 性能優(yōu)化 共享主機(jī)環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
テキスト

查詢構(gòu)建器

查詢構(gòu)建器

查詢構(gòu)建器建立在?Database Access Objects?基礎(chǔ)之上,可讓你創(chuàng)建 程序化的、DBMS無關(guān)的SQL語(yǔ)句。相比于原生的SQL語(yǔ)句,查詢構(gòu)建器可以幫你 寫出可讀性更強(qiáng)的SQL相關(guān)的代碼,并生成安全性更強(qiáng)的SQL語(yǔ)句。

使用查詢構(gòu)建器通常包含以下兩個(gè)步驟:

  1. 創(chuàng)建一個(gè) yii\db\Query 對(duì)象來代表一條 SELECT SQL 語(yǔ)句的不同子句(例如?SELECT,?FROM)。
  2. 執(zhí)行 yii\db\Query 的一個(gè)查詢方法(例如:all())從數(shù)據(jù)庫(kù)當(dāng)中檢索數(shù)據(jù)。

如下所示代碼是查詢構(gòu)造器的一個(gè)典型用法:

$rows = (new \yii\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->limit(10)
    ->all();

上面的代碼將會(huì)生成并執(zhí)行如下的SQL語(yǔ)句,其中?:last_name?參數(shù)綁定了 字符串?'Smith'。

SELECT `id`, `email` 
FROM `user`WHERE `last_name` = :last_name
LIMIT 10

提示: 你平時(shí)更多的時(shí)候會(huì)使用 yii\db\Query 而不是 [yii\db\QueryBuilder]]。 當(dāng)你調(diào)用其中一個(gè)查詢方法時(shí),后者將會(huì)被前者隱式的調(diào)用。yii\db\QueryBuilder主要負(fù)責(zé)將 DBMS 不相關(guān)的 yii\db\Query 對(duì)象轉(zhuǎn)換成 DBMS 相關(guān)的 SQL 語(yǔ)句(例如, 以不同的方式引用表或字段名稱)。

創(chuàng)建查詢

為了創(chuàng)建一個(gè) yii\db\Query 對(duì)象,你需要調(diào)用不同的查詢構(gòu)建方法來代表SQL語(yǔ)句的不同子句。 這些方法的名稱集成了在SQL語(yǔ)句相應(yīng)子句中使用的關(guān)鍵字。例如,為了指定 SQL 語(yǔ)句當(dāng)中的?FROM?子句,你應(yīng)該調(diào)用?from()?方法。所有的查詢構(gòu)建器方法返回的是查詢對(duì)象本身, 也就是說,你可以把多個(gè)方法的調(diào)用串聯(lián)起來。

接下來,我們會(huì)對(duì)這些查詢構(gòu)建器方法進(jìn)行一一講解:

yii\db\Query::select()

yii\db\Query::select() 方法用來指定 SQL 語(yǔ)句當(dāng)中的?SELECT?子句。 你可以像下面的例子一樣使用一個(gè)數(shù)組或者字符串來定義需要查詢的字段。當(dāng) SQL 語(yǔ)句 是由查詢對(duì)象生成的時(shí)候,被查詢的字段名稱將會(huì)自動(dòng)的被引號(hào)括起來。

$query->select(['id', 'email']);

// 等同于:

$query->select('id, email');

就像寫原生 SQL 語(yǔ)句一樣,被選取的字段可以包含表前綴,以及/或者字段別名。 例如:

$query->select(['user.id AS user_id', 'email']);

// 等同于:

$query->select('user.id AS user_id, email');

如果使用數(shù)組格式來指定字段,你可以使用數(shù)組的鍵值來表示字段的別名。 例如,上面的代碼可以被重寫為如下形式:

$query->select(['user_id' => 'user.id', 'email']);

如果你在組建查詢時(shí)沒有調(diào)用 yii\db\Query::select() 方法,那么選擇的將是?'*'?, 也即選取的是所有的字段。

除了字段名稱以外,你還可以選擇數(shù)據(jù)庫(kù)的表達(dá)式。當(dāng)你使用到包含逗號(hào)的數(shù)據(jù)庫(kù)表達(dá)式的時(shí)候, 你必須使用數(shù)組的格式,以避免自動(dòng)的錯(cuò)誤的引號(hào)添加。例如:

$query->select(["CONCAT(first_name, ' ', last_name) AS full_name", 'email']); 

從 2.0.1 的版本開始你就可以使用子查詢了。在定義每一個(gè)子查詢的時(shí)候, 你應(yīng)該使用 yii\db\Query 對(duì)象。例如:

$subQuery = (new Query())->select('COUNT(*)')->from('user');

// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`$query = (new Query())->select(['id', 'count' => $subQuery])->from('post');

你應(yīng)該調(diào)用 yii\db\Query::distinct() 方法來去除重復(fù)行,如下所示:

// SELECT DISTINCT `user_id` ...$query->select('user_id')->distinct();

你可以調(diào)用 yii\db\Query::addSelect() 方法來選取附加字段,例如:

$query->select(['id', 'username'])
    ->addSelect(['email']);

yii\db\Query::from()

yii\db\Query::from() 方法指定了 SQL 語(yǔ)句當(dāng)中的?FROM?子句。例如:

// SELECT * FROM `user`$query->from('user');

你可以通過字符串或者數(shù)組的形式來定義被查詢的表名稱。就像你寫原生的 SQL 語(yǔ)句一樣, 表名稱里面可包含數(shù)據(jù)庫(kù)前綴,以及/或者表別名。例如:

$query->from(['public.user u', 'public.post p']);

// 等同于:

$query->from('public.user u, public.post p');

如果你使用的是數(shù)組的格式,那么你同樣可以用數(shù)組的鍵值來定義表別名,如下所示:

$query->from(['u' => 'public.user', 'p' => 'public.post']);

除了表名以外,你還可以從子查詢中再次查詢,這里的子查詢是由 yii\db\Query 創(chuàng)建的對(duì)象。 例如:

$subQuery = (new Query())->select('id')->from('user')->where('status=1');

// SELECT * FROM (SELECT `id` FROM `user` WHERE status=1) u $query->from(['u' => $subQuery]);

yii\db\Query::where()

yii\db\Query::where() 方法定義了 SQL 語(yǔ)句當(dāng)中的?WHERE?子句。 你可以使用如下三種格式來定義?WHERE?條件:

  • 字符串格式,例如:'status=1'
  • 哈希格式,例如:?['status' => 1, 'type' => 2]
  • 操作符格式,例如:['like', 'name', 'test']

字符串格式

在定義非常簡(jiǎn)單的查詢條件的時(shí)候,字符串格式是最合適的。它看起來和原生 SQL 語(yǔ)句差不多。例如:

$query->where('status=1');

// 或者使用參數(shù)綁定來綁定動(dòng)態(tài)參數(shù)值$query->where('status=:status', [':status' => $status]);

千萬(wàn)不要像如下的例子一樣直接在條件語(yǔ)句當(dāng)中嵌入變量,特別是當(dāng)這些變量來源于終端用戶輸入的時(shí)候, 因?yàn)檫@樣我們的軟件將很容易受到 SQL 注入的攻擊。

// 危險(xiǎn)!千萬(wàn)別這樣干,除非你非常的確定 $status 是一個(gè)整型數(shù)值。$query->where("status=$status");

當(dāng)使用參數(shù)綁定的時(shí)候,你可以調(diào)用 yii\db\Query::params() 或者 yii\db\Query::addParams() 方法 來分別綁定不同的參數(shù)。

$query->where('status=:status')
    ->addParams([':status' => $status]);

哈希格式

哈希格式最適合用來指定多個(gè)?AND?串聯(lián)起來的簡(jiǎn)單的"等于斷言"子條件。 它是以數(shù)組的形式來書寫的,數(shù)組的鍵表示字段的名稱,而數(shù)組的值則表示 這個(gè)字段需要匹配的值。例如:

// ...WHERE (`status` = 10) AND (`type` IS NULL) AND (`id` IN (4, 8, 15))$query->where([
    'status' => 10,
    'type' => null,
    'id' => [4, 8, 15],
]);

就像你所看到的一樣,查詢構(gòu)建器非常的智能,能恰當(dāng)?shù)靥幚頂?shù)值當(dāng)中的空值和數(shù)組。

你也可以像下面那樣在子查詢當(dāng)中使用哈希格式:

$userQuery = (new Query())->select('id')->from('user');

// ...WHERE `id` IN (SELECT `id` FROM `user`)$query->where(['id' => $userQuery]);

操作符格式

操作符格式允許你指定類程序風(fēng)格的任意條件語(yǔ)句,如下所示:

[操作符, 操作數(shù)1, 操作數(shù)2, ...]

其中每個(gè)操作數(shù)可以是字符串格式、哈希格式或者嵌套的操作符格式,而操作符可以是如下列表中的一個(gè):

  • and: 操作數(shù)會(huì)被?AND?關(guān)鍵字串聯(lián)起來。例如,['and', 'id=1', 'id=2']?將會(huì)生成?id=1 AND id=2。如果操作數(shù)是一個(gè)數(shù)組,它也會(huì)按上述規(guī)則轉(zhuǎn)換成 字符串。例如,['and', 'type=1', ['or', 'id=1', 'id=2']]?將會(huì)生成?type=1 AND (id=1 OR id=2)。 這個(gè)方法不會(huì)自動(dòng)加引號(hào)或者轉(zhuǎn)義。

  • or: 用法和?and?操作符類似,這里就不再贅述。

  • between: 第一個(gè)操作數(shù)為字段名稱,第二個(gè)和第三個(gè)操作數(shù)代表的是這個(gè)字段 的取值范圍。例如,['between', 'id', 1, 10]?將會(huì)生成?id BETWEEN 1 AND 10。

  • not between: 用法和?BETWEEN?操作符類似,這里就不再贅述。

  • in: 第一個(gè)操作數(shù)應(yīng)為字段名稱或者 DB 表達(dá)式。第二個(gè)操作符既可以是一個(gè)數(shù)組, 也可以是一個(gè)?Query?對(duì)象。它會(huì)轉(zhuǎn)換成IN條件語(yǔ)句。如果第二個(gè)操作數(shù)是一個(gè) 數(shù)組,那么它代表的是字段或 DB 表達(dá)式的取值范圍。如果第二個(gè)操作數(shù)是?Query?對(duì)象,那么這個(gè)子查詢的結(jié)果集將會(huì)作為第一個(gè)操作符的字段或者 DB 表達(dá)式的取值范圍。 例如,?['in', 'id', [1, 2, 3]]?將生成?id IN (1, 2, 3)。 該方法將正確地為字段名加引號(hào)以及為取值范圍轉(zhuǎn)義。in?操作符還支持組合字段,此時(shí), 操作數(shù)1應(yīng)該是一個(gè)字段名數(shù)組,而操作數(shù)2應(yīng)該是一個(gè)數(shù)組或者?Query?對(duì)象, 代表這些字段的取值范圍。

  • not in: 用法和?in?操作符類似,這里就不再贅述。

  • like: 第一個(gè)操作數(shù)應(yīng)為一個(gè)字段名稱或 DB 表達(dá)式,第二個(gè)操作數(shù)可以使字符串或數(shù)組, 代表第一個(gè)操作數(shù)需要模糊查詢的值。比如,['like', 'name', 'tester']?會(huì)生成?name LIKE '%tester%'。 如果范圍值是一個(gè)數(shù)組,那么將會(huì)生成用?AND?串聯(lián)起來的 多個(gè)?like?語(yǔ)句。例如,['like', 'name', ['test', 'sample']]?將會(huì)生成?name LIKE '%test%' AND name LIKE '%sample%'。 你也可以提供第三個(gè)可選的操作數(shù)來指定應(yīng)該如何轉(zhuǎn)義數(shù)值當(dāng)中的特殊字符。 該操作數(shù)是一個(gè)從需要被轉(zhuǎn)義的特殊字符到轉(zhuǎn)義副本的數(shù)組映射。 如果沒有提供這個(gè)操作數(shù),將會(huì)使用默認(rèn)的轉(zhuǎn)義映射。如果需要禁用轉(zhuǎn)義的功能, 只需要將參數(shù)設(shè)置為?false?或者傳入一個(gè)空數(shù)組即可。需要注意的是, 當(dāng)使用轉(zhuǎn)義映射(又或者沒有提供第三個(gè)操作數(shù)的時(shí)候),第二個(gè)操作數(shù)的值的前后 將會(huì)被加上百分號(hào)。

> 注意:當(dāng)使用 PostgreSQL 的時(shí)候你還可以使用?ilike, > 該方法對(duì)大小寫不敏感。

  • or like: 用法和?like?操作符類似,區(qū)別在于當(dāng)?shù)诙€(gè)操作數(shù)為數(shù)組時(shí), 會(huì)使用?OR?來串聯(lián)多個(gè)?LIKE?條件語(yǔ)句。

  • not like: 用法和?like?操作符類似,區(qū)別在于會(huì)使用?NOT LIKE?來生成條件語(yǔ)句。

  • or not like: 用法和?not like?操作符類似,區(qū)別在于會(huì)使用?OR?來串聯(lián)多個(gè)?NOT LIKE?條件語(yǔ)句。

  • exists: 需要一個(gè)操作數(shù),該操作數(shù)必須是代表子查詢 yii\db\Query 的一個(gè)實(shí)例, 它將會(huì)構(gòu)建一個(gè)?EXISTS (sub-query)?表達(dá)式。

  • not exists: 用法和?exists?操作符類似,它將創(chuàng)建一個(gè)?NOT EXISTS (sub-query)?表達(dá)式。

  • >,?<=, 或者其他包含兩個(gè)操作數(shù)的合法 DB 操作符: 第一個(gè)操作數(shù)必須為字段的名稱, 而第二個(gè)操作數(shù)則應(yīng)為一個(gè)值。例如,['>', 'age', 10]?將會(huì)生成?age>10。

附加條件

你可以使用 yii\db\Query::andWhere() 或者 yii\db\Query::orWhere() 在原有條件的基礎(chǔ)上 附加額外的條件。你可以多次調(diào)用這些方法來分別追加不同的條件。 例如,

$status = 10;
$search = 'yii';

$query->where(['status' => $status]);

if (!empty($search)) {
    $query->andWhere(['like', 'title', $search]);
}

如果?$search?不為空,那么將會(huì)生成如下 SQL 語(yǔ)句:

... WHERE (`status` = 10) AND (`title` LIKE '%yii%')

過濾條件

當(dāng)?WHERE?條件來自于用戶的輸入時(shí),你通常需要忽略用戶輸入的空值。 例如,在一個(gè)可以通過用戶名或者郵箱搜索的表單當(dāng)中,用戶名或者郵箱 輸入框沒有輸入任何東西,這種情況下你想要忽略掉對(duì)應(yīng)的搜索條件, 那么你就可以使用 yii\db\Query::filterWhere() 方法來實(shí)現(xiàn)這個(gè)目的:

// $username 和 $email 來自于用戶的輸入$query->filterWhere([
    'username' => $username,
    'email' => $email,           
]);

yii\db\Query::filterWhere() 和 yii\db\Query::where() 唯一的不同就在于,前者 將忽略在條件當(dāng)中的hash format的空值。所以如果$email?為空而?$username?不為空,那么上面的代碼最終將生產(chǎn)如下 SQL?...WHERE username=:username。

提示:當(dāng)一個(gè)值為 null、空數(shù)組、空字符串或者一個(gè)只包含空白字符時(shí),那么它將被判定為空值。

類似于 [yii\db\Query::andWhere()|andWhere()]] 和 yii\db\Query::orWhere(), 你可以使用 yii\db\Query::andFilterWhere() 和 yii\db\Query::orFilterWhere() 方法 來追加額外的過濾條件。

yii\db\Query::orderBy()

yii\db\Query::orderBy() 方法是用來指定 SQL 語(yǔ)句當(dāng)中的?ORDER BY?子句的。例如,

// ... ORDER BY `id` ASC, `name` DESC$query->orderBy([
    'id' => SORT_ASC,
    'name' => SORT_DESC,
]);

如上所示,數(shù)組當(dāng)中的鍵指代的是字段名稱,而數(shù)組當(dāng)中的值則表示的是排序的方式。 PHP 的常量?SORT_ASC?指的是升序排列,SORT_DESC?指的則是降序排列。

如果?ORDER BY?僅僅包含簡(jiǎn)單的字段名稱,你可以使用字符串來聲明它, 就像寫原生的 SQL 語(yǔ)句一樣。例如,

$query->orderBy('id ASC, name DESC');

注意:當(dāng)?ORDER BY?語(yǔ)句包含一些 DB 表達(dá)式的時(shí)候,你應(yīng)該使用數(shù)組的格式。

你可以調(diào)用 [yii\db\Query::addOrderBy()|addOrderBy()]] 來為?ORDER BY?片斷添加額外的子句。 例如,

$query->orderBy('id ASC')
    ->addOrderBy('name DESC');

yii\db\Query::groupBy()

yii\db\Query::groupBy() 方法是用來指定 SQL 語(yǔ)句當(dāng)中的?GROUP BY?片斷的。例如,

// ... GROUP BY `id`, `status`$query->groupBy(['id', 'status']);

如果?GROUP BY?僅僅包含簡(jiǎn)單的字段名稱,你可以使用字符串來聲明它, 就像寫原生的 SQL 語(yǔ)句一樣。例如,

$query->groupBy('id, status');

注意:當(dāng)?GROUP BY?語(yǔ)句包含一些 DB 表達(dá)式的時(shí)候,你應(yīng)該使用數(shù)組的格式。

你可以調(diào)用 [yii\db\Query::addOrderBy()|addOrderBy()]] 來為?GROUP BY?子句添加額外的字段。例如,

$query->groupBy(['id', 'status'])
    ->addGroupBy('age');

yii\db\Query::having()

yii\db\Query::having() 方法是用來指定 SQL 語(yǔ)句當(dāng)中的?HAVING?子句。它帶有一個(gè)條件, 和?where()?中指定條件的方法一樣。例如,

// ... HAVING `status` = 1$query->having(['status' => 1]);

請(qǐng)查閱?where()?的文檔來獲取更多有關(guān)于如何指定一個(gè)條件的細(xì)節(jié)。

你可以調(diào)用 yii\db\Query::andHaving() 或者 yii\db\Query::orHaving() 方法來為?HAVING?子句追加額外的條件,例如,

// ... HAVING (`status` = 1) AND (`age` > 30)$query->having(['status' => 1])
    ->andHaving(['>', 'age', 30]);

yii\db\Query::limit() 和 yii\db\Query::offset()

yii\db\Query::limit() 和 yii\db\Query::offset() 是用來指定 SQL 語(yǔ)句當(dāng)中 的?LIMIT?和?OFFSET?子句的。例如,

// ... LIMIT 10 OFFSET 20$query->limit(10)->offset(20);

如果你指定了一個(gè)無效的 limit 或者 offset(例如,一個(gè)負(fù)數(shù)),那么它將會(huì)被忽略掉。

提示:在不支持?LIMIT?和?OFFSET?的 DBMS 中(例如,MSSQL), 查詢構(gòu)建器將生成一條模擬?LIMIT/OFFSET?行為的 SQL 語(yǔ)句。

yii\db\Query::join()

[yii\db\Query::join()|join()]] 是用來指定 SQL 語(yǔ)句當(dāng)中的?JOIN?子句的。例如,
`php
// ... LEFT JOIN?post?ON?post.user_id?=?user.id
$query->join('LEFT JOIN', 'post', 'post.user_id = user.id');
`

yii\db\Query::join() 帶有四個(gè)參數(shù):

  • $type: 連接類型,例如:'INNER JOIN',?'LEFT JOIN'。
  • $table: 將要連接的表名稱。
  • $on: 可選參數(shù),連接條件,即?ON?子句。請(qǐng)查閱?where()?獲取更多有關(guān)于條件定義的細(xì)節(jié)。
  • $params: 可選參數(shù),與連接條件綁定的參數(shù)。

你可以分別調(diào)用如下的快捷方法來指定?INNER JOIN,?LEFT JOIN?和?RIGHT JOIN。

  • yii\db\Query::innerJoin()
  • yii\db\Query::leftJoin()
  • yii\db\Query::rightJoin()

例如,

$query->leftJoin('post', 'post.user_id = user.id');

可以通過多次調(diào)用如上所述的連接方法來連接多張表,每連接一張表調(diào)用一次。

除了連接表以外,你還可以連接子查詢。方法如下,將需要被連接的子查詢指定 為一個(gè) yii\db\Query 對(duì)象,例如,

$subQuery = (new \yii\db\Query())->from('post');
$query->leftJoin(['u' => $subQuery], 'u.id = author_id');

在這個(gè)例子當(dāng)中,你應(yīng)該將子查詢放到一個(gè)數(shù)組當(dāng)中,而數(shù)組當(dāng)中的鍵,則為這個(gè)子查詢的別名。

yii\db\Query::union()

yii\db\Query::union() 方法是用來指定 SQL 語(yǔ)句當(dāng)中的?UNION?子句的。例如,

$query1 = (new \yii\db\Query())
    ->select("id, category_id AS type, name")
    ->from('post')
    ->limit(10);

$query2 = (new \yii\db\Query())
    ->select('id, type, name')
    ->from('user')
    ->limit(10);

$query1->union($query2);

你可以通過多次調(diào)用 yii\db\Query::union() 方法來追加更多的?UNION?子句。

查詢方法

yii\db\Query 提供了一整套的用于不同查詢目的的方法。

  • yii\db\Query::all(): 將返回一個(gè)由行組成的數(shù)組,每一行是一個(gè)由名稱和值構(gòu)成的關(guān)聯(lián)數(shù)組(譯者注:省略鍵的數(shù)組稱為索引數(shù)組)。
  • yii\db\Query::one(): 返回結(jié)果集的第一行。
  • yii\db\Query::column(): 返回結(jié)果集的第一列。
  • yii\db\Query::scalar(): 返回結(jié)果集的第一行第一列的標(biāo)量值。
  • yii\db\Query::exists(): 返回一個(gè)表示該查詢是否包結(jié)果集的值。
  • yii\db\Query::count(): 返回?COUNT?查詢的結(jié)果。
  • 其它集合查詢方法: 包括 yii\db\Query::sum(), yii\db\Query::average(), yii\db\Query::max(), yii\db\Query::min() 等.?$q?是一個(gè)必選參數(shù), 既可以是一個(gè)字段名稱,又可以是一個(gè) DB 表達(dá)式。

例如,

// SELECT `id`, `email` FROM `user`$rows = (new \yii\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->all();
    
// SELECT * FROM `user` WHERE `username` LIKE `%test%`$row = (new \yii\db\Query())
    ->from('user')
    ->where(['like', 'username', 'test'])
    ->one();

注意:yii\db\Query::one() 方法只返回查詢結(jié)果當(dāng)中的第一條數(shù)據(jù), 條件語(yǔ)句中不會(huì)加上?LIMIT 1?條件。如果你清楚的知道查詢將會(huì)只返回一行或幾行數(shù)據(jù) (例如, 如果你是通過某些主鍵來查詢的),這很好也提倡這樣做。但是,如果查詢結(jié)果 有機(jī)會(huì)返回大量的數(shù)據(jù)時(shí),那么你應(yīng)該顯示調(diào)用?limit(1)?方法,以改善性能。 例如,?(new \yii\db\Query())->from('user')->limit(1)->one()。

所有的這些查詢方法都有一個(gè)可選的參數(shù)?$db, 該參數(shù)指代的是 yii\db\Connection, 執(zhí)行一個(gè) DB 查詢時(shí)會(huì)用到。如果你省略了這個(gè)參數(shù),那么?db?application component?將會(huì)被用作 默認(rèn)的 DB 連接。 如下是另外一個(gè)使用?count()?查詢的例子:

// 執(zhí)行 SQL: SELECT COUNT(*) FROM `user` WHERE `last_name`=:last_name$count = (new \yii\db\Query())
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->count();

當(dāng)你調(diào)用 yii\db\Query 當(dāng)中的一個(gè)查詢方法的時(shí)候,實(shí)際上內(nèi)在的運(yùn)作機(jī)制如下:

  • 在當(dāng)前 yii\db\Query 的構(gòu)造基礎(chǔ)之上,調(diào)用 yii\db\QueryBuilder 來生成一條 SQL 語(yǔ)句;
  • 利用生成的 SQL 語(yǔ)句創(chuàng)建一個(gè) yii\db\Command 對(duì)象;
  • 調(diào)用 yii\db\Command 的查詢方法(例如,queryAll())來執(zhí)行這條 SQL 語(yǔ)句,并檢索數(shù)據(jù)。

有時(shí)候,你也許想要測(cè)試或者使用一個(gè)由 yii\db\Query 對(duì)象創(chuàng)建的 SQL 語(yǔ)句。 你可以使用以下的代碼來達(dá)到目的:

$command = (new \yii\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->limit(10)
    ->createCommand();
    
// 打印 SQL 語(yǔ)句echo $command->sql;
// 打印被綁定的參數(shù)
print_r($command->params);

// 返回查詢結(jié)果的所有行$rows = $command->queryAll();

索引查詢結(jié)果

當(dāng)你在調(diào)用 yii\db\Query::all() 方法時(shí),它將返回一個(gè)以連續(xù)的整型數(shù)值為索引的數(shù)組。 而有時(shí)候你可能希望使用一個(gè)特定的字段或者表達(dá)式的值來作為索引結(jié)果集數(shù)組。那么你可以在調(diào)用 yii\db\Query::all() 之前使用 yii\db\Query::indexBy() 方法來達(dá)到這個(gè)目的。 例如,

// 返回 [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 => [...], ...]$query = (new \yii\db\Query())
    ->from('user')
    ->limit(10)
    ->indexBy('id')
    ->all();

如需使用表達(dá)式的值做為索引,那么只需要傳遞一個(gè)匿名函數(shù)給 yii\db\Query::indexBy() 方法即可:

$query = (new \yii\db\Query())
    ->from('user')
    ->indexBy(function ($row) {
        return $row['id'] . $row['username'];
    })->all();

該匿名函數(shù)將帶有一個(gè)包含了當(dāng)前行的數(shù)據(jù)的?$row?參數(shù),并且返回用作當(dāng)前行索引的 標(biāo)量值(譯者注:就是簡(jiǎn)單的數(shù)值或者字符串,而不是其他復(fù)雜結(jié)構(gòu),例如數(shù)組)。

批處理查詢

當(dāng)需要處理大數(shù)據(jù)的時(shí)候,像 yii\db\Query::all() 這樣的方法就不太合適了, 因?yàn)樗鼈儠?huì)把所有數(shù)據(jù)都讀取到內(nèi)存上。為了保持較低的內(nèi)存需求, Yii 提供了一個(gè) 所謂的批處理查詢的支持。批處理查詢會(huì)利用數(shù)據(jù)游標(biāo)將數(shù)據(jù)以批為單位取出來。

批處理查詢的用法如下:

use yii\db\Query;

$query = (new Query())
    ->from('user')
    ->orderBy('id');

foreach ($query->batch() as $users) {
    // $users 是一個(gè)包含100條或小于100條用戶表數(shù)據(jù)的數(shù)組
}

// or if you want to iterate the row one by oneforeach ($query->each() as $user) {
    // $user 指代的是用戶表當(dāng)中的其中一行數(shù)據(jù)
}

yii\db\Query::batch() 和 yii\db\Query::each() 方法將會(huì)返回一個(gè)實(shí)現(xiàn)了Iterator?接口 yii\db\BatchQueryResult 的對(duì)象,可以用在foreach?結(jié)構(gòu)當(dāng)中使用。在第一次迭代取數(shù)據(jù)的時(shí)候, 數(shù)據(jù)庫(kù)會(huì)執(zhí)行一次 SQL 查詢,然后在剩下的迭代中,將直接從結(jié)果集中批量獲取數(shù)據(jù)。默認(rèn)情況下, 一批的大小為 100,也就意味著一批獲取的數(shù)據(jù)是 100 行。你可以通過給?batch()?或者?each()?方法的第一個(gè)參數(shù)傳值來改變每批行數(shù)的大小。

相對(duì)于 yii\db\Query::all() 方法,批處理查詢每次只讀取 100 行的數(shù)據(jù)到內(nèi)存。 如果你在處理完這些數(shù)據(jù)后及時(shí)丟棄這些數(shù)據(jù),那么批處理查詢可以很好的幫助降低內(nèi)存的占用率。

如果你通過 yii\db\Query::indexBy() 方法為查詢結(jié)果指定了索引字段,那么批處理查詢將仍然保持相對(duì)應(yīng)的索引方案,例如,

$query?=?(new?\yii\db\Query())
? ? ->from('user')
? ? ->indexBy('username');

foreach?($query->batch()?as?$users)?{
? ? //?$users?的?“username”?字段將會(huì)成為索引
}

foreach?($query->each()?as?$username?=>?$user)?{
}
前の記事: 次の記事: