Commit 7b0f6669 by Nobuo Kihara

docs/guide-ja/db-query-builder.md - completed [ci skip]

parent b38c2179
...@@ -200,81 +200,71 @@ $query->where(['id' => $userQuery]); ...@@ -200,81 +200,71 @@ $query->where(['id' => $userQuery]);
WHERE `id` IN (SELECT `id` FROM `user`) WHERE `id` IN (SELECT `id` FROM `user`)
``` ```
このメソッドを使うもう一つの方法は、`[演算子, オペランド1, オペランド2, ...]` という演算形式です。 このメソッドを使うもう一つの方法は、`[演算子, オペランド1, オペランド2, ...]` という形式の引数を使う方法です。
Another way to use the method is the operand format which is `[operator, operand1, operand2, ...]`.
Operator can be one of the following (see also [[yii\db\QueryInterface::where()]]): 演算子には、次のどれか一つを使うことが出来ます ([[yii\db\QueryInterface::where()]] も参照してください)。
- `and`: the operands should be concatenated together using `AND`. For example, - `and`: 二つのオペランドが `AND` を使って結合されます。例えば、`['and', 'id=1', 'id=2']``id=1 AND id=2` を生成します。
`['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. If an operand is an array, オペランドが配列である場合は、ここで説明されている規則に従って文字列に変換されます。
it will be converted into a string using the rules described here. For example, 例えば、`['and', 'type=1', ['or', 'id=1', 'id=2']]``type=1 AND (id=1 OR id=2)` を生成します。
`['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`. このメソッドは、文字列を引用符で囲ったりエスケープしたりしません。
The method will NOT do any quoting or escaping.
- `or`: similar to the `and` operator except that the operands are concatenated using `OR`. - `or`: 二つのオペランドが `OR` を使って結合されること以外は `and` 演算子と同じです。
- `between`: operand 1 should be the column name, and operand 2 and 3 should be the - `between`: オペランド 1 はカラム名、オペランド 2 と 3 はカラムの値が属すべき範囲の開始値と終了値としなければなりません。
starting and ending values of the range that the column is in. 例えば、`['between', 'id', 1, 10]``id BETWEEN 1 AND 10` を生成します。
For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`.
- `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN` - `not between`: 生成される条件において `BETWEEN``NOT BETWEEN` に置き換えられる以外は、`between` と同じです。
in the generated condition.
- `in`: operand 1 should be a column or DB expression. Operand 2 can be either an array or a `Query` object. - `in`: オペランド 1 はカラム名または DB 式でなければなりません。
It will generate an `IN` condition. If Operand 2 is an array, it will represent the range of the values オペランド 2 は、配列または `Query` オブジェクトのどちらかを取ることが出来ます。
that the column or DB expression should be; If Operand 2 is a `Query` object, a sub-query will be generated オペランド 2 が配列である場合は、その配列は、カラムまたは DB 式が該当すべき値域を表すものとされます。
and used as the range of the column or DB expression. For example, オペランド 2 が `Query` オブジェクトである場合は、サブクエリが生成されて、カラムまたは DB 式の値域として使われます。
`['in', 'id', [1, 2, 3]]` will generate `id IN (1, 2, 3)`. 例えば、`['in', 'id', [1, 2, 3]]``id IN (1, 2, 3)` を生成します。
The method will properly quote the column name and escape values in the range. このメソッドは、カラム名を適切に引用符で囲み、値域の値をエスケープします。
The `in` operator also supports composite columns. In this case, operand 1 should be an array of the columns, `in` 演算子はまた複合カラムをもサポートしています。
while operand 2 should be an array of arrays or a `Query` object representing the range of the columns. その場合、オペランド 1 はカラム名の配列とし、オペランド 2 は配列の配列、または、複合カラムの値域を表す `Query` オブジェクトでなければなりません。
- `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition. - `not in`: 生成される条件において `IN``NOT IN` に置き換えられる以外は、`in` と同じです。
- `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing - `like`: オペランド 1 はカラム名または DB 式、オペランド 2 はカラムまたは DB 式がマッチすべき値を示す文字列または配列でなければなりません。
the values that the column or DB expression should be like. 例えば、`['like', 'name', 'tester']``name LIKE '%tester%'` を生成します。
For example, `['like', 'name', 'tester']` will generate `name LIKE '%tester%'`. 値域が配列として与えられた場合は、複数の `LIKE` 述語が生成されて 'AND' によって結合されます。
When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated 例えば、`['like', 'name', ['test', 'sample']]``name LIKE '%test%' AND name LIKE '%sample%'` を生成します。
using `AND`. For example, `['like', 'name', ['test', 'sample']]` will generate さらに、オプションである三番目のオペランドによって、値の中の特殊文字をエスケープする方法を指定することも出来ます。
`name LIKE '%test%' AND name LIKE '%sample%'`. このオペランド 3 は、特殊文字とそのエスケープ結果のマッピングを示す配列でなければなりません。
You may also provide an optional third operand to specify how to escape special characters in the values. このオペランドが提供されない場合は、デフォルトのエスケープマッピングが使用されます。
The operand should be an array of mappings from the special characters to their `false` または空の配列を使って、値が既にエスケープ済みであり、それ以上エスケープを適用すべきでないことを示すことが出来ます。
escaped counterparts. If this operand is not provided, a default escape mapping will be used. エスケープマッピングを使用する場合 (または第三のオペランドが与えられない場合) は、値が自動的に一組のパーセント記号によって囲まれることに注意してください。
You may use `false` or an empty array to indicate the values are already escaped and no escape
should be applied. Note that when using an escape mapping (or the third operand is not provided),
the values will be automatically enclosed within a pair of percentage characters.
> Note: When using PostgreSQL you may also use [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) > Note|注意: PostgreSQL を使っている場合は、`like` の代りに、大文字と小文字を区別しない比較のための [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) を使うことも出来ます。
> instead of `like` for case-insensitive matching.
- `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE` - `or like`: オペランド 2 が配列である場合に `LIKE` 述語が `OR` によって結合される以外は、`like` 演算子と同じです。
predicates when operand 2 is an array.
- `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE` - `not like`: 生成される条件において `LIKE``NOT LIKE` に置き換えられる以外は、`like` 演算子と同じです。
in the generated condition.
- `or not like`: similar to the `not like` operator except that `OR` is used to concatenate - `or not like`: `NOT LIKE` 述語が `OR` によって結合される以外は、`not like` 演算子と同じです。
the `NOT LIKE` predicates.
- `exists`: requires one operand which must be an instance of [[yii\db\Query]] representing the sub-query. - `exists`: 要求される一つだけのオペランドは、サブクエリを表す [[yii\db\Query]] のインスタンスでなければなりません。
It will build a `EXISTS (sub-query)` expression. これは `EXISTS (sub-query)` という式を構築します。
- `not exists`: similar to the `exists` operator and builds a `NOT EXISTS (sub-query)` expression. - `not exists`: `exists` 演算子と同じで、`NOT EXISTS (sub-query)` という式を構築します。
Additionally you can specify anything as operator: これらに加えて、どのようなものでも演算子として指定することが出来ます。
```php ```php
$userQuery = (new Query)->select('id')->from('user'); $query->select('id')
$query->where(['>=', 'id', 10]); ->from('user')
->where(['>=', 'id', 10]);
``` ```
It will result in: これは次の結果になります。
```sql ```sql
SELECT id FROM user WHERE id >= 10; SELECT id FROM user WHERE id >= 10;
``` ```
If you are building parts of condition dynamically it's very convenient to use `andWhere()` and `orWhere()`: 条件の一部を動的に構築しようとする場合は、`andWhere()``orWhere()` を使うのが非常に便利です。
```php ```php
$status = 10; $status = 10;
...@@ -286,40 +276,40 @@ if (!empty($search)) { ...@@ -286,40 +276,40 @@ if (!empty($search)) {
} }
``` ```
In case `$search` isn't empty the following SQL will be generated: `$search` が空でない場合は次の SQL が生成されます。
```sql ```sql
WHERE (`status` = 10) AND (`title` LIKE '%yii%') WHERE (`status` = 10) AND (`title` LIKE '%yii%')
``` ```
#### Building Filter Conditions #### フィルタの条件を構築する
When building filter conditions based on user inputs, you usually want to specially handle "empty inputs" ユーザの入力に基づいてフィルタの条件を構築する場合、普通は、「空の入力値」は特別扱いして、フィルタではそれを無視したいものです。
by ignoring them in the filters. For example, you have an HTML form that takes username and email inputs. 例えば、ユーザ名とメールアドレスの入力欄を持つ HTML フォームがあるとします。
If the user only enters something in the username input, you may want to build a query that only tries to ユーザがユーザ名の入力欄のみに何かを入力した場合は、入力されたユーザ名だけを検索条件とするクエリを作成したいでしょう。
match the entered username. You may use the `filterWhere()` method achieve this goal: この目的を達するために `filterWhere()` メソッドを使うことが出来ます。
```php ```php
// $username and $email are from user inputs // $username と $email はユーザの入力による
$query->filterWhere([ $query->filterWhere([
'username' => $username, 'username' => $username,
'email' => $email, 'email' => $email,
]); ]);
``` ```
The `filterWhere()` method is very similar to `where()`. The main difference is that `filterWhere()` `filterWhere()` メソッドは `where()` と非常によく似ています。
will remove empty values from the provided condition. So if `$email` is "empty", the resulting query 主な相違点は、`filterWhere()` は与えられた条件から空の値を削除する、ということです。
will be `...WHERE username=:username`; and if both `$username` and `$email` are "empty", the query 従って、`$email` が「空」である場合は、結果として生成されるクエリは `...WHERE username=:username` となります。
will have no `WHERE` part. そして、`$username``$email` が両方とも「空」である場合は、クエリは `WHERE` の部分を持ちません。
A value is *empty* if it is null, an empty string, a string consisting of whitespaces, or an empty array. 値が *空* であるのは、null、空文字列、空白文字だけの文字列、または、空配列である場合です。
You may also use `andFilterWhere()` and `orFilterWhere()` to append more filter conditions. フィルタの条件を追加するために、`andFilterWhere()``orFilterWhere()` を使うことも出来ます。
### `ORDER BY` ### `ORDER BY`
For ordering results `orderBy` and `addOrderBy` could be used: 結果を並び替えるために `orderBy``addOrderBy` を使うことが出来ます。
```php ```php
$query->orderBy([ $query->orderBy([
...@@ -328,38 +318,38 @@ $query->orderBy([ ...@@ -328,38 +318,38 @@ $query->orderBy([
]); ]);
``` ```
Here we are ordering by `id` ascending and then by `name` descending. ここでは `id` の昇順、`name` の降順で並べ替えています。
### `GROUP BY` and `HAVING` ### `GROUP BY` `HAVING`
In order to add `GROUP BY` to generated SQL you can use the following: 生成される SQL に `GROUP BY` を追加するためには、次のようにすることが出来ます。
```php ```php
$query->groupBy('id, status'); $query->groupBy('id, status');
``` ```
If you want to add another field after using `groupBy`: `groupBy` を使った後に別のフィールドを追加したい場合は、
```php ```php
$query->addGroupBy(['created_at', 'updated_at']); $query->addGroupBy(['created_at', 'updated_at']);
``` ```
To add a `HAVING` condition the corresponding `having` method and its `andHaving` and `orHaving` can be used. Parameters `HAVING` 条件を追加したい場合は、それに対応する `having` メソッドおよび `andHaving``orHaving` を使うことが出来ます。
for these are similar to the ones for `where` methods group: これらのメソッドのパラメータは、`where` メソッドグループのそれと同様です。
```php ```php
$query->having(['status' => $status]); $query->having(['status' => $status]);
``` ```
### `LIMIT` and `OFFSET` ### `LIMIT` `OFFSET`
To limit result to 10 rows `limit` can be used: 結果を 10 行に限定したいときは、`limit` を使うことが出来ます。
```php ```php
$query->limit(10); $query->limit(10);
``` ```
To skip 100 fist rows use: 最初の 100 行をスキップしたい時は、こうします。
```php ```php
$query->offset(100); $query->offset(100);
...@@ -367,13 +357,13 @@ $query->offset(100); ...@@ -367,13 +357,13 @@ $query->offset(100);
### `JOIN` ### `JOIN`
The `JOIN` clauses are generated in the Query Builder by using the applicable join method: 適切な結合メソッドを使って、クエリビルダで `JOIN` 句を生成することが出来ます。
- `innerJoin()` - `innerJoin()`
- `leftJoin()` - `leftJoin()`
- `rightJoin()` - `rightJoin()`
This left join selects data from two related tables in one query: 次の左外部結合では、二つの関連テーブルから一つのクエリでデータを取得しています。
```php ```php
$query->select(['user.name AS author', 'post.title as title']) $query->select(['user.name AS author', 'post.title as title'])
...@@ -381,20 +371,21 @@ $query->select(['user.name AS author', 'post.title as title']) ...@@ -381,20 +371,21 @@ $query->select(['user.name AS author', 'post.title as title'])
->leftJoin('post', 'post.user_id = user.id'); ->leftJoin('post', 'post.user_id = user.id');
``` ```
In the code, the `leftJoin()` method's first parameter このコードにおいて、`leftJoin()` メソッドの最初のパラメータは、結合するテーブルを指定するものです。
specifies the table to join to. The second parameter defines the join condition. 第二のパラメータは、結合の条件を定義しています。
If your database application supports other join types, you can use those via the generic `join` method: データベース製品がその他の結合タイプをサポートしている場合は、汎用の `join` メソッドによってそれを使うことが出来ます。
```php ```php
$query->join('FULL OUTER JOIN', 'post', 'post.user_id = user.id'); $query->join('FULL OUTER JOIN', 'post', 'post.user_id = user.id');
``` ```
The first argument is the join type to perform. The second is the table to join to, and the third is the condition. 最初のパラメータが実行する結合タイプです。第二は結合するテーブル、第三は結合の条件です。
Like `FROM`, you may also join with sub-queries. To do so, specify the sub-query as an array `FROM` と同様に、サブクエリを結合することも出来ます。
which must contain one element. The array value must be a `Query` object representing the sub-query, そのためには、一つの要素を持つ配列としてサブクエリを指定します。
while the array key is the alias for the sub-query. For example, 配列の値はサブクエリを表す `Query` オブジェクトとし、配列のキーはサブクエリのエイリアスとしなければなりません。
例えば、
```php ```php
$query->leftJoin(['u' => $subQuery], 'u.id=author_id'); $query->leftJoin(['u' => $subQuery], 'u.id=author_id');
...@@ -403,8 +394,9 @@ $query->leftJoin(['u' => $subQuery], 'u.id=author_id'); ...@@ -403,8 +394,9 @@ $query->leftJoin(['u' => $subQuery], 'u.id=author_id');
### `UNION` ### `UNION`
`UNION` in SQL adds results of one query to results of another query. Columns returned by both queries should match. SQL における `UNION` は、一つのクエリの結果を別のクエリの結果に追加するものです。
In Yii in order to build it you can first form two query objects and then use `union` method: 両方のクエリによって返されるカラムが一致していなければなりません。
Yii においてこれを構築するためには、最初に二つのクエリオブジェクトを作成し、次に `union` メソッドを使って連結します。
```php ```php
$query = new Query(); $query = new Query();
...@@ -417,15 +409,15 @@ $query->union($anotherQuery); ...@@ -417,15 +409,15 @@ $query->union($anotherQuery);
``` ```
Batch Query バッチクエリ
----------- ------------
When working with large amount of data, methods such as [[yii\db\Query::all()]] are not suitable 大量のデータを扱う場合は、[[yii\db\Query::all()]] のようなメソッドは適していません。
because they require loading all data into the memory. To keep the memory requirement low, Yii なぜなら、それらのメソッドは、全てのデータをメモリ上に読み込むことを必要とするためです。
provides the so-called batch query support. A batch query makes uses of data cursor and fetches 必要なメモリ量を低く抑えるために、Yii はいわゆるバッチクエリのサポートを提供しています。
data in batches. バッチクエリはデータカーソルを利用して、バッチモードでデータを取得します。
Batch query can be used like the following: バッチクエリは次のようにして使うことが出来ます。
```php ```php
use yii\db\Query; use yii\db\Query;
...@@ -435,26 +427,26 @@ $query = (new Query()) ...@@ -435,26 +427,26 @@ $query = (new Query())
->orderBy('id'); ->orderBy('id');
foreach ($query->batch() as $users) { foreach ($query->batch() as $users) {
// $users is an array of 100 or fewer rows from the user table // $users は user テーブルから取得した 100 以下の行の配列
} }
// or if you want to iterate the row one by one // または、一行ずつ反復したい場合は
foreach ($query->each() as $user) { foreach ($query->each() as $user) {
// $user represents one row of data from the user table // $user は user テーブルから取得した一つの行を表す
} }
``` ```
The method [[yii\db\Query::batch()]] and [[yii\db\Query::each()]] return an [[yii\db\BatchQueryResult]] object [[yii\db\Query::batch()]] メソッドと [[yii\db\Query::each()]] メソッドは [[yii\db\BatchQueryResult]] オブジェクトを返します。
which implements the `Iterator` interface and thus can be used in the `foreach` construct. このオブジェクトは `Iterator` インタフェイスを実装しており、従って、`foreach` 構文の中で使うことが出来ます。
During the first iteration, a SQL query is made to the database. Data are since then fetched in batches 初回の反復の際に、データベースに対する SQL クエリが作成されます。データは、その後、反復のたびにバッチモードで取得されます。
in the iterations. By default, the batch size is 100, meaning 100 rows of data are being fetched in each batch. 既定では、バッチサイズは 100 であり、各バッチにおいて 100 行のデータが取得されます。
You can change the batch size by passing the first parameter to the `batch()` or `each()` method. `batch()` または `each()` メソッドに最初のパラメータを渡すことによって、バッチサイズを変更することが出来ます。
Compared to the [[yii\db\Query::all()]], the batch query only loads 100 rows of data at a time into the memory. [[yii\db\Query::all()]] とは対照的に、バッチクエリは一度に 100 行のデータしかメモリに読み込みません。
If you process the data and then discard it right away, the batch query can help keep the memory usage under a limit. データを処理した後、すぐにデータを破棄するようにすれば、バッチクエリの助けを借りてメモリ消費量を限度以下に抑えることが出来ます。
If you specify the query result to be indexed by some column via [[yii\db\Query::indexBy()]], the batch query [[yii\db\Query::indexBy()]] によってクエリ結果をあるカラムでインデックスするように指定している場合でも、バッチクエリは正しいインデックスを保持します。
will still keep the proper index. For example, 例えば、
```php ```php
use yii\db\Query; use yii\db\Query;
...@@ -464,7 +456,7 @@ $query = (new Query()) ...@@ -464,7 +456,7 @@ $query = (new Query())
->indexBy('username'); ->indexBy('username');
foreach ($query->batch() as $users) { foreach ($query->batch() as $users) {
// $users is indexed by the "username" column // $users は "username" カラムでインデックスされている
} }
foreach ($query->each() as $username => $user) { foreach ($query->each() as $username => $user) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment