1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20766 -->
4 <sect1 id="zend.db.select">
6 <title>Zend_Db_Select</title>
8 <sect2 id="zend.db.select.introduction">
13 <classname>Zend_Db_Select</classname> オブジェクトは、<acronym>SQL</acronym> の <acronym>SELECT</acronym> 文を表すものです。
14 このクラスには、クエリの各部分を追加するためのメソッドが用意されています。
15 <acronym>PHP</acronym> のメソッドやデータをもとにクエリの各部分を指定すると、
16 このクラスが正確な <acronym>SQL</acronym> 文を作成してくれます。クエリを作成したら、
17 あとは通常の文字列と同じようにそれを用いてクエリを実行できます。
21 <classname>Zend_Db_Select</classname> は次のような機能を提供します。
27 <acronym>SQL</acronym> クエリを少しずつ組み立てていくための
34 <acronym>SQL</acronym> クエリの一部について、データベースに依存しない抽象化
40 大半のメタデータ識別子の自動クォート処理による、
41 予約語や特殊文字を含む <acronym>SQL</acronym> のサポート
48 <acronym>SQL</acronym> インジェクション攻撃対策
54 必ず <classname>Zend_Db_Select</classname> を使わなければならないというわけではありません。
55 単純な SELECT クエリを実行するのなら、<acronym>SQL</acronym> クエリ全体を文字列で指定し、
56 アダプタの <methodname>query()</methodname> メソッドや <methodname>fetchAll()</methodname>
57 メソッドを使用したほうがずっとシンプルになるでしょう。
58 <classname>Zend_Db_Select</classname> を使うと便利なのは、
59 何らかの条件にもとづいて、アプリケーション内で
60 SELECT クエリを動的に組み立てていく必要があるような場合です。
65 <sect2 id="zend.db.select.creating">
67 <title>Select オブジェクトの作成</title>
70 <classname>Zend_Db_Select</classname> オブジェクトのインスタンスを作成するには、
71 <classname>Zend_Db_Adapter_Abstract</classname> オブジェクトの
72 <methodname>select()</methodname> メソッドを使用します。
75 <example id="zend.db.select.creating.example-db">
77 <title>データベースアダプタの select() メソッドの例</title>
79 <programlisting language="php"><![CDATA[
80 $db = Zend_Db::factory( ...options... );
81 $select = $db->select();
86 <classname>Zend_Db_Select</classname> オブジェクトを作成するもうひとつの方法は、
87 コンストラクタの引数でデータベースアダプタを指定することです。
90 <example id="zend.db.select.creating.example-new">
92 <title>新しい Select オブジェクトの作成の例</title>
94 <programlisting language="php"><![CDATA[
95 $db = Zend_Db::factory( ...options... );
96 $select = new Zend_Db_Select($db);
102 <sect2 id="zend.db.select.building">
104 <title>Select クエリの作成</title>
107 クエリを作成する際に、クエリの句を個別に追加していくことができます。
108 <classname>Zend_Db_Select</classname> オブジェクトには、
109 個々の句を追加していくメソッドが用意されています。
112 <example id="zend.db.select.building.example">
114 <title>メソッドを使用して句を追加する例</title>
116 <programlisting language="php"><![CDATA[
117 // Zend_Db_Select オブジェクトを作成します
118 $select = $db->select();
121 $select->from( ...テーブルとカラムを指定します... )
124 $select->where( ...検索条件を指定します... )
127 $select->order( ...ソート条件を指定します... );
132 <classname>Zend_Db_Select</classname> オブジェクトの大半のメソッドで、便利な
133 「流れるようなインターフェイス」形式を利用できます。これは、
134 各メソッドが、自分自身への参照を結果として返すということです。
135 つまり、その結果を使用してすぐに別のメソッドをコールできるのです。
138 <example id="zend.db.select.building.example-fluent">
140 <title>流れるようなインターフェイスの使用例</title>
142 <programlisting language="php"><![CDATA[
143 $select = $db->select()
144 ->from( ...テーブルとカラムを指定します... )
145 ->where( ...検索条件を指定します... )
146 ->order( ...ソート条件を指定します... );
152 この節の例では流れるようなインターフェイスを使用しますが、
153 この方式を使用せずに使用することも可能です。
154 そうしなければならないこともよくあるでしょう。たとえば、
155 クエリに句を追加する前にアプリケーションで何らかの処理が必要な場合などです。
158 <sect3 id="zend.db.select.building.from">
160 <title>FROM 句の追加</title>
163 このクエリのテーブルを指定するために <methodname>from()</methodname>
164 メソッドを使用します。テーブル名は、単純に文字列で指定できます。
165 <classname>Zend_Db_Select</classname> はテーブル名を識別子としてクォートするので、
169 <example id="zend.db.select.building.from.example">
171 <title>from() メソッドの例</title>
173 <programlisting language="php"><![CDATA[
174 // できあがるクエリは、このようになります
178 $select = $db->select()
179 ->from( 'products' );
185 テーブルの相関名 (あるいは "エイリアス" とも言われます)
187 単純な文字列ではなく連想配列を使用し、相関名とテーブル名の対応を指定します。
188 <acronym>SQL</acronym> のその他の句で、この相関名を使用できるようになります。
189 複数のテーブルを結合したクエリを作成する場合は、
190 <classname>Zend_Db_Select</classname> はそのテーブル名に基づいた一意な相関名を作成します。
193 <example id="zend.db.select.building.from.example-cname">
195 <title>テーブルの相関名を指定する例</title>
197 <programlisting language="php"><![CDATA[
198 // できあがるクエリは、このようになります
200 // FROM "products" AS p
202 $select = $db->select()
203 ->from( array('p' => 'products') );
209 <acronym>RDBMS</acronym> によっては、テーブル名の前にスキーマ名をつなげる方式をサポートしているものもあります。
210 テーブル名として、"<code>schemaName.tableName</code>"
212 <classname>Zend_Db_Select</classname> は各部分を個別にクォートします。
213 あるいはスキーマ名とテーブル名を別々に指定することもできます。
215 テーブル名と同時に指定したもののほうが優先されます。
218 <example id="zend.db.select.building.from.example-schema">
220 <title>スキーマ名の指定の例</title>
222 <programlisting language="php"><![CDATA[
223 // できあがるクエリは、このようになります
225 // FROM "myschema"."products"
227 $select = $db->select()
228 ->from( 'myschema.products' );
232 $select = $db->select()
233 ->from('products', '*', 'myschema');
240 <sect3 id="zend.db.select.building.columns">
242 <title>カラムの追加</title>
245 <methodname>from()</methodname> メソッドの二番目の引数で、
246 対応するテーブルから取得するカラムを指定できます。
248 "<code>*</code>" で、これは "すべてのカラム"
249 を表す <acronym>SQL</acronym> のワイルドカードです。
253 カラム名を指定するには、単純な文字列の配列を使用するか、
254 あるいは連想配列でエイリアスとカラム名を対応させます。
255 取得したいカラムがひとつだけの場合でエイリアスを使用しない場合は、
256 配列ではなく単純な文字列で指定することもできます。
261 対応するテーブルからのカラムは結果セットに含まれなくなります。
262 <methodname>join()</methodname> メソッドの
263 <link linkend="zend.db.select.building.join.example-no-columns">コード例</link>
269 "<code>correlationName.columnName</code>"
270 の形式で指定することもできます。この場合、
271 <classname>Zend_Db_Select</classname> は各部分を個別にクォートします。
272 カラムの correlationName (相関名) を指定しなかった場合は、
273 現在の <methodname>from()</methodname> メソッドで指定したテーブルの名前を使用します。
276 <example id="zend.db.select.building.columns.example">
278 <title>カラムを指定する例</title>
280 <programlisting language="php"><![CDATA[
281 // できあがるクエリは、このようになります
282 // SELECT p."product_id", p."product_name"
283 // FROM "products" AS p
285 $select = $db->select()
286 ->from(array('p' => 'products'),
287 array('product_id', 'product_name'));
289 // 同じクエリを、相関名を指定して作成します
290 // SELECT p."product_id", p."product_name"
291 // FROM "products" AS p
293 $select = $db->select()
294 ->from(array('p' => 'products'),
295 array('p.product_id', 'p.product_name'));
297 // このクエリを、カラムのひとつにエイリアスを指定して作成します
298 // SELECT p."product_id" AS prodno, p."product_name"
299 // FROM "products" AS p
301 $select = $db->select()
302 ->from(array('p' => 'products'),
303 array('prodno' => 'product_id', 'product_name'));
310 <sect3 id="zend.db.select.building.columns-expr">
312 <title>式によるカラムの追加</title>
315 <acronym>SQL</acronym> クエリでは、単にテーブルのカラムを使用するだけでなく
316 何らかの式をカラムとして使用することもあります。
317 このような場合は、相関名をつけたりクォートを適用したりしてはいけません。
318 カラム文字列に括弧が含まれている場合に、<classname>Zend_Db_Select</classname>
323 <classname>Zend_Db_Expr</classname> 型のオブジェクトを明示的に作成し、
324 文字列がカラム名と解釈されてしまうことを防ぐこともできます。
325 <classname>Zend_Db_Expr</classname> は、文字列をひとつだけ含む最小限のクラスです。
326 <classname>Zend_Db_Select</classname> は <code>Zend_Db_Expr</code> 型のオブジェクトを認識し、
328 その際にクォートや相関名などの処理を適用しません。
334 カラムとして使用する式に括弧が含まれている場合は、
335 カラム名で <classname>Zend_Db_Expr</classname> を指定する必要はありません。
336 <classname>Zend_Db_Select</classname> は、括弧を発見すると自動的にその文字列を式として扱います。
342 <example id="zend.db.select.building.columns-expr.example">
344 <title>式を含むカラムの指定の例</title>
346 <programlisting language="php"><![CDATA[
347 // できあがるクエリは、このようになります
348 // SELECT p."product_id", LOWER(product_name)
349 // FROM "products" AS p
351 // Zend_Db_Expr として扱われます
353 $select = $db->select()
354 ->from(array('p' => 'products'),
355 array('product_id', 'LOWER(product_name)'));
357 // できあがるクエリは、このようになります
358 // SELECT p."product_id", (p.cost * 1.08) AS cost_plus_tax
359 // FROM "products" AS p
361 $select = $db->select()
362 ->from(array('p' => 'products'),
364 'cost_plus_tax' => '(p.cost * 1.08)')
367 // このクエリを、明示的に Zend_Db_Expr を指定して作成します
368 // SELECT p."product_id", p.cost * 1.08 AS cost_plus_tax
369 // FROM "products" AS p
371 $select = $db->select()
372 ->from(array('p' => 'products'),
375 new Zend_Db_Expr('p.cost * 1.08'))
382 上の例では、<classname>Zend_Db_Select</classname> は
383 相関名の設定や識別子のクォートといった処理を行いません。
384 あいまいさを解決するためにそのような処理が必要な場合は、
389 カラム名が <acronym>SQL</acronym> キーワードや特殊文字を含んでいる場合は、
390 アダプタの <methodname>quoteIdentifier()</methodname>
391 メソッドを使用して結果を操作する必要があります。
392 <methodname>quoteIdentifier()</methodname> は、
393 識別子に対して <acronym>SQL</acronym> のクォート処理を行います。
394 これによりテーブルやカラムといった識別子を
395 <acronym>SQL</acronym> のそれ以外の部分と区別できるようになります。
399 クォート処理を直接文字列に埋め込んでしまわずに
400 <methodname>quoteIdentifier()</methodname> メソッドを使用することで、
401 あなたのコードをデータベースに依存しないものにできます。
402 というのも、<acronym>RDBMS</acronym> によってはあまり標準的ではない文字でクォートを行うものもあるからです。
403 <methodname>quoteIdentifier()</methodname> メソッドは、
404 アダプタの型に応じて適切なクォート文字を使用するように設計されています。
405 <methodname>quoteIdentifier()</methodname> メソッドはまた、
406 識別子の名前の中に登場するクォート文字自体もエスケープします。
409 <example id="zend.db.select.building.columns-quoteid.example">
411 <title>式の中のカラムをクォートする例</title>
413 <programlisting language="php"><![CDATA[
414 // このクエリを作成する際に、式の中にある特別なカラム名 "from" をクォートします
415 // SELECT p."from" + 10 AS origin
416 // FROM "products" AS p
418 $select = $db->select()
419 ->from(array('p' => 'products'),
421 '(p.' . $db->quoteIdentifier('from') . ' + 10)')
429 <sect3 id="zend.db.select.building.columns-atomic">
431 <title>既存の FROM あるいは JOIN テーブルへのカラムの追加</title>
434 既存の FROM や JOIN のテーブルに対して、それらのメソッドをコールした後で
435 カラムを追加したくなることもあるかもしれません。
436 <methodname>columns()</methodname> メソッドを使用すると、
437 クエリを実行する前ならいつでも好きなときに特定のカラムを追加できます。
438 カラムは、文字列あるいは <classname>Zend_Db_Expr</classname>、
440 このメソッドの 2 番目の引数は省略可能です。
441 省略した場合は、FROM テーブルにカラムが追加されます。
442 指定する場合は、既存の相関名を使用しなければなりません。
445 <example id="zend.db.select.building.columns-atomic.example">
447 <title>columns() メソッドでカラムを追加する例</title>
449 <programlisting language="php"><![CDATA[
450 // できあがるクエリは、このようになります
451 // SELECT p."product_id", p."product_name"
452 // FROM "products" AS p
454 $select = $db->select()
455 ->from(array('p' => 'products'), 'product_id')
456 ->columns('product_name');
458 // 同じクエリを、相関名を指定して作成します
459 // SELECT p."product_id", p."product_name"
460 // FROM "products" AS p
462 $select = $db->select()
463 ->from(array('p' => 'products'), 'p.product_id')
464 ->columns('product_name', 'p');
465 // あるいは columns('p.product_name')
472 <sect3 id="zend.db.select.building.join">
474 <title>JOIN による、クエリへの別のテーブルの追加</title>
477 有用なクエリの多くは、<acronym>JOIN</acronym>
478 を使用して複数テーブルの行を結合しています。
479 テーブルを <classname>Zend_Db_Select</classname> クエリに追加するには、
480 <methodname>join()</methodname> メソッドを使用します。
481 このメソッドの使用法は <methodname>from()</methodname>
482 メソッドと似ていますが、ほとんどの場合に結合条件を指定するという点が異なります。
485 <example id="zend.db.select.building.join.example">
487 <title>join() メソッドの例</title>
489 <programlisting language="php"><![CDATA[
490 // できあがるクエリは、このようになります
491 // SELECT p."product_id", p."product_name", l.*
492 // FROM "products" AS p JOIN "line_items" AS l
493 // ON p.product_id = l.product_id
495 $select = $db->select()
496 ->from(array('p' => 'products'),
497 array('product_id', 'product_name'))
498 ->join(array('l' => 'line_items'),
499 'p.product_id = l.product_id');
505 <methodname>join()</methodname> の二番目の引数として、
507 あるテーブルの行が別のテーブルのどの行と対応するのかを表す条件式です。
514 結合条件に指定した式に関しては、クォート処理は行われません。
515 クォートする必要のあるカラム名を使用する場合は、
517 <methodname>quoteIdentifier()</methodname> を使用しなければなりません。
523 <methodname>join()</methodname> の三番目の引数はカラム名を表す配列です。
524 これは <methodname>from()</methodname> メソッドで使用する形式と似ています。
525 デフォルトは "<code>*</code>" です。
526 相関名や式、<classname>Zend_Db_Expr</classname> についての扱いは、
527 <methodname>from()</methodname> メソッドにおけるカラム名の配列と同じです。
533 これは <methodname>from()</methodname> メソッドでも同様に動作しますが、
534 普通は最初のテーブルからは何らかのカラムを取得するでしょう。
535 一方、連結するテーブルについてはカラムを取得しないこともありえます。
538 <example id="zend.db.select.building.join.example-no-columns">
540 <title>カラムを指定しない例</title>
542 <programlisting language="php"><![CDATA[
543 // できあがるクエリは、このようになります
544 // SELECT p."product_id", p."product_name"
545 // FROM "products" AS p JOIN "line_items" AS l
546 // ON p.product_id = l.product_id
548 $select = $db->select()
549 ->from(array('p' => 'products'),
550 array('product_id', 'product_name'))
551 ->join(array('l' => 'line_items'),
552 'p.product_id = l.product_id',
553 array() ); // 空のカラムリスト
557 上の例で、連結したテーブルのカラム一覧の場所に
558 空の配列 <methodname>array()</methodname> を指定していることに注意しましょう。
564 <acronym>SQL</acronym> の結合にはいくつかの形式があります。
565 以下に、<classname>Zend_Db_Select</classname> がサポートする結合の形式をまとめます。
571 <methodname>join(table, join, [columns])</methodname> メソッドあるいは
572 <methodname>joinInner(table, join, [columns])</methodname> メソッドによる
573 <command>INNER JOIN</command>
577 これはもっとも一般的な結合形式です。各テーブルの行を、
579 結果セットには、その結合条件を満たす行のみが含まれます。
580 条件を満たす行がない場合は、結果セットが空になることもあります。
584 すべての <acronym>RDBMS</acronym> が、この結合形式に対応しています。
590 <methodname>joinLeft(table, condition, [columns])</methodname> メソッドによる
591 <command>LEFT JOIN</command>
596 右側のテーブルの条件にマッチする行が含まれます。
598 左側のテーブルに対応する行がないものについては
599 <constant>NULL</constant> で埋められます。
603 すべての <acronym>RDBMS</acronym> が、この結合形式に対応しています。
609 <methodname>joinRight(table, condition, [columns])</methodname> メソッドによる
610 <command>RIGHT JOIN</command>
614 右外部結合は、左外部結合を補完するものです。
616 左側のテーブルの条件にマッチする行が含まれます。
618 右側のテーブルに対応する行がないものについては
619 <constant>NULL</constant> で埋められます。
623 <acronym>RDBMS</acronym> によっては、この結合形式に対応していないものもあります。
625 テーブルの順番を入れ替えれば左外部結合として表すことが可能です。
631 <methodname>joinFull(table, condition, [columns])</methodname> メソッドによる
632 <command>FULL JOIN</command>
636 完全外部結合は、左外部結合と右外部結合を組み合わせたようなものです。
638 結合条件を満たす組み合わせがあった場合はそれらが同一行にまとめられ、
639 それ以外の場合は、対応するデータがないカラムについては <constant>NULL</constant> で埋められます。
643 <acronym>RDBMS</acronym> によっては、この結合形式に対応していないものもあります。
649 <methodname>joinCross(table, [columns])</methodname> メソッドによる
650 <command>CROSS JOIN</command>
656 二番目のテーブルのすべての行がマッチします。
658 ふたつのテーブルの行数の積と等しくなります。
659 結果セットをフィルタリングするには、WHERE
661 この方法によるクロス結合は、昔の SQL-89
666 <methodname>joinCross()</methodname> メソッドには、
667 結合条件を指定するパラメータがありません。
668 <acronym>RDBMS</acronym> によっては、この結合形式に対応していないものもあります。
674 <methodname>joinNatural(table, [columns])</methodname> メソッドによる
675 <command>NATURAL JOIN</command>
679 自然結合は、両方のテーブルに同じ名前で登場するカラムを比較します。
681 この <acronym>API</acronym> でサポートしているのは、自然内部結合のみです。
682 <acronym>SQL</acronym> で自然外部結合がサポートされていたとしても、使用できません。
686 <methodname>joinNatural()</methodname> メソッドには、
687 結合条件を指定するパラメータはありません。
693 これらの結合メソッドに加え、クエリを単純にするために
694 JoinUsing メソッドを使用できます。完全な結合条件を渡すかわりに、
695 単純に結合するカラム名の配列を渡してやれば
696 <classname>Zend_Db_Select</classname> オブジェクトが結合条件を作成してくれます。
699 <example id="zend.db.select.building.joinusing.example">
701 <title>joinUsing() メソッドの例</title>
703 <programlisting language="php"><![CDATA[
704 // できあがるクエリは、このようになります
708 // ON "table1".column1 = "table2".column1
709 // WHERE column2 = 'foo'
711 $select = $db->select()
713 ->joinUsing('table2', 'column1')
714 ->where('column2 = ?', 'foo');]]></programlisting>
719 <classname>Zend_Db_Select</classname> の結合メソッドには、
720 それぞれ対応する 'using' メソッドがあります。
726 <methodname>joinUsing(table, join, [columns])</methodname> および
727 <methodname>joinInnerUsing(table, join, [columns])</methodname>
733 <methodname>joinLeftUsing(table, join, [columns])</methodname>
739 <methodname>joinRightUsing(table, join, [columns])</methodname>
745 <methodname>joinFullUsing(table, join, [columns])</methodname>
752 <sect3 id="zend.db.select.building.where">
754 <title>WHERE 句の追加</title>
757 結果セットの行を制限するための条件を指定するには
758 <methodname>where()</methodname> メソッドを使用します。
759 このメソッドの最初の引数は <acronym>SQL</acronym> の式で、これをクエリの
760 <acronym>SQL</acronym> で <acronym>WHERE</acronym> 句として使用します。
763 <example id="zend.db.select.building.where.example">
765 <title>where() メソッドの例</title>
767 <programlisting language="php"><![CDATA[
768 // できあがるクエリは、このようになります
769 // SELECT product_id, product_name, price
771 // WHERE price > 100.00
773 $select = $db->select()
775 array('product_id', 'product_name', 'price'))
776 ->where('price > 100.00');]]></programlisting>
783 <methodname>where()</methodname> メソッドや <methodname>orWhere()</methodname>
784 メソッドで指定する式にはクォート処理は行われません。
785 クォートする必要のあるカラム名を使用する場合は、
787 <methodname>quoteIdentifier()</methodname> を使用しなければなりません。
793 <methodname>where()</methodname> メソッドの二番目の引数はオプションです。
795 <classname>Zend_Db_Select</classname> は値をクォートし、式の中の
796 クエスチョンマーク ("<code>?</code>") をその値で置き換えます。
799 <example id="zend.db.select.building.where.example-param">
801 <title>where() メソッドでのパラメータの例</title>
803 <programlisting language="php"><![CDATA[
804 // できあがるクエリは、このようになります
805 // SELECT product_id, product_name, price
807 // WHERE (price > 100.00)
811 $select = $db->select()
813 array('product_id', 'product_name', 'price'))
814 ->where('price > ?', $minimumPrice);
820 SQL の IN 演算子を使うとき、 <methodname>where()</methodname> メソッドに
824 <example id="zend.db.select.building.where.example-array">
826 <title>where() メソッドでの配列パラメータ例</title>
828 <programlisting language="php"><![CDATA[
830 // SELECT product_id, product_name, price
832 // WHERE (product_id IN (1, 2, 3))
834 $productIds = array(1, 2, 3);
836 $select = $db->select()
838 array('product_id', 'product_name', 'price'))
839 ->where('product_id IN (?)', $productIds);
845 <classname>Zend_Db_Select</classname> オブジェクト上で、<methodname>where()</methodname>
846 メソッドを複数回実行することもできます。その結果のクエリは、
847 指定した条件を <acronym>AND</acronym> でひとつにまとめたものとなります。
850 <example id="zend.db.select.building.where.example-and">
852 <title>複数の where() メソッドの例</title>
854 <programlisting language="php"><![CDATA[
855 // できあがるクエリは、このようになります
856 // SELECT product_id, product_name, price
858 // WHERE (price > 100.00)
859 // AND (price < 500.00)
864 $select = $db->select()
866 array('product_id', 'product_name', 'price'))
867 ->where('price > ?', $minimumPrice)
868 ->where('price < ?', $maximumPrice);
874 複数の条件を <acronym>OR</acronym> で連結したい場合は、
875 <methodname>orWhere()</methodname> メソッドを使用します。
876 このメソッドの使用法は <methodname>where()</methodname>
877 メソッドとほとんど同じですが、条件の前には
878 <acronym>AND</acronym> ではなく <acronym>OR</acronym>
882 <example id="zend.db.select.building.where.example-or">
884 <title>orWhere() メソッドの例</title>
886 <programlisting language="php"><![CDATA[
887 // できあがるクエリは、このようになります
888 // SELECT product_id, product_name, price
890 // WHERE (price < 100.00)
891 // OR (price > 500.00)
896 $select = $db->select()
898 array('product_id', 'product_name', 'price'))
899 ->where('price < ?', $minimumPrice)
900 ->orWhere('price > ?', $maximumPrice);
906 <classname>Zend_Db_Select</classname> は、<methodname>where()</methodname> メソッドや
907 <methodname>orWhere()</methodname> メソッドで指定した式の両側に
909 論理演算子が予期せぬ結果を引き起こすことを防ぎます。
912 <example id="zend.db.select.building.where.example-parens">
914 <title>論理式を括弧で囲む例</title>
916 <programlisting language="php"><![CDATA[
917 // できあがるクエリは、このようになります
918 // SELECT product_id, product_name, price
920 // WHERE (price < 100.00 OR price > 500.00)
921 // AND (product_name = 'Apple')
927 $select = $db->select()
929 array('product_id', 'product_name', 'price'))
930 ->where("price < $minimumPrice OR price > $maximumPrice")
931 ->where('product_name = ?', $prod);
937 上の例では、括弧がなければ結果はまったく異なるものとなります。
938 なぜなら、<acronym>AND</acronym> のほうが <acronym>OR</acronym>
939 よりも優先順位が高いからです。<classname>Zend_Db_Select</classname>
940 は括弧をつけるので、それぞれの <methodname>where()</methodname>
941 で指定された式の結合度が <acronym>AND</acronym>
947 <sect3 id="zend.db.select.building.group">
949 <title>GROUP BY 句の追加</title>
952 <acronym>SQL</acronym> で <command>GROUP BY</command> 句を使用すると、
954 <command>GROUP BY</command> 句で指定したカラムの一意な値ごとに、
959 <classname>Zend_Db_Select</classname> では、行のグループ化を行うためのカラムを
960 <methodname>group()</methodname> メソッドで指定します。
961 このメソッドへの引数は、<command>GROUP BY</command>
962 句で使用するカラムあるいは複数カラムの配列となります。
965 <example id="zend.db.select.building.group.example">
967 <title>group() メソッドの例</title>
969 <programlisting language="php"><![CDATA[
970 // できあがるクエリは、このようになります
971 // SELECT p."product_id", COUNT(*) AS line_items_per_product
972 // FROM "products" AS p JOIN "line_items" AS l
973 // ON p.product_id = l.product_id
974 // GROUP BY p.product_id
976 $select = $db->select()
977 ->from(array('p' => 'products'),
979 ->join(array('l' => 'line_items'),
980 'p.product_id = l.product_id',
981 array('line_items_per_product' => 'COUNT(*)'))
982 ->group('p.product_id');
988 <methodname>from()</methodname> メソッドでのカラムの配列と同様、
992 <classname>Zend_Db_Expr</classname> 型のオブジェクトを指定したりした場合は別です。
997 <sect3 id="zend.db.select.building.having">
999 <title>HAVING 句の追加</title>
1002 <acronym>SQL</acronym> で <constant>HAVING</constant> 句を使用すると、
1003 グループ化した行に制約を適用します。これは、
1004 <constant>WHERE</constant> 句が行に対して制約を適用するのと同じです。
1006 <constant>WHERE</constant> 条件はグループ化の前に適用されますが、
1007 <constant>HAVING</constant> 条件はグループ化された後に適用されます。
1011 <classname>Zend_Db_Select</classname> では、グループに対する制約を指定するには
1012 <methodname>having()</methodname> メソッドを使用します。
1013 このメソッドの使用法は <methodname>where()</methodname> メソッドと似ています。
1014 最初の引数が <acronym>SQL</acronym> の式を含む文字列です。二番目の引数はオプションで、
1015 <acronym>SQL</acronym> 式の中のパラメータプレースホルダを置き換える値となります。
1016 <methodname>having()</methodname> を複数回実行すると、それらの条件が
1017 論理演算子 <constant>AND</constant> で連結されます。
1018 <methodname>orHaving()</methodname> メソッドを使用した場合は、論理演算子
1019 <code>OR</code> で連結されます。
1022 <example id="zend.db.select.building.having.example">
1024 <title>having() メソッドの例</title>
1026 <programlisting language="php"><![CDATA[
1027 // できあがるクエリは、このようになります
1028 // SELECT p."product_id", COUNT(*) AS line_items_per_product
1029 // FROM "products" AS p JOIN "line_items" AS l
1030 // ON p.product_id = l.product_id
1031 // GROUP BY p.product_id
1032 // HAVING line_items_per_product > 10
1034 $select = $db->select()
1035 ->from(array('p' => 'products'),
1036 array('product_id'))
1037 ->join(array('l' => 'line_items'),
1038 'p.product_id = l.product_id',
1039 array('line_items_per_product' => 'COUNT(*)'))
1040 ->group('p.product_id')
1041 ->having('line_items_per_product > 10');
1042 ]]></programlisting>
1049 <methodname>having()</methodname> メソッドや <methodname>orHaving()</methodname>
1050 メソッドで指定する式にはクォート処理は行われません。
1051 クォートする必要のあるカラム名を使用する場合は、
1053 <methodname>quoteIdentifier()</methodname> を使用しなければなりません。
1060 <sect3 id="zend.db.select.building.order">
1062 <title>ORDER BY 句の追加</title>
1065 <acronym>SQL</acronym> の <code>ORDER BY</code> 句では、
1066 クエリの結果セットの並べ替えの基準となるカラムや式を指定します。
1067 複数のカラムを指定すると、最初のカラムの値が同じだった場合に
1068 二番目のカラムを用いて並べ替えを行います。
1069 デフォルトでは、小さいほうから大きいほうに向かって並べ替えます。
1070 逆に大きいほうから小さいほうに向かって並べ替えるには、
1071 カラムリストの中のそのカラム名の後に、キーワード
1072 <constant>DESC</constant> を指定します。
1076 <classname>Zend_Db_Select</classname> では、<methodname>order()</methodname> メソッドを使用して
1077 並べ替えの基準となるカラムあるいはカラムの配列を指定します。
1078 配列の各要素はカラム名を表す文字列です。オプションとして、
1080 <constant>ASC</constant> や <constant>DESC</constant> を続けます。
1084 <methodname>from()</methodname> メソッドや <methodname>group()</methodname>
1085 メソッドと同様、カラム名は識別子としてクォートされます。
1087 <classname>Zend_Db_Expr</classname> 型のオブジェクトを指定したりした場合は別です。
1090 <example id="zend.db.select.building.order.example">
1092 <title>order() メソッドの例</title>
1094 <programlisting language="php"><![CDATA[
1095 // できあがるクエリは、このようになります
1096 // SELECT p."product_id", COUNT(*) AS line_items_per_product
1097 // FROM "products" AS p JOIN "line_items" AS l
1098 // ON p.product_id = l.product_id
1099 // GROUP BY p.product_id
1100 // ORDER BY "line_items_per_product" DESC, "product_id"
1102 $select = $db->select()
1103 ->from(array('p' => 'products'),
1104 array('product_id'))
1105 ->join(array('l' => 'line_items'),
1106 'p.product_id = l.product_id',
1107 array('line_items_per_product' => 'COUNT(*)'))
1108 ->group('p.product_id')
1109 ->order(array('line_items_per_product DESC',
1111 ]]></programlisting>
1117 <sect3 id="zend.db.select.building.limit">
1119 <title>LIMIT 句の追加</title>
1122 <acronym>RDBMS</acronym> によっては、<acronym>SQL</acronym> を拡張して、いわゆる
1123 <constant>LIMIT</constant> 句を使用できるようにしているものもあります。
1124 これは、結果セットの行数を、最大でも指定した数までに制限します。
1125 また、出力を始める前に読み飛ばす行数を指定することもできます。
1126 この機能を使用すると、結果セットの一部だけを取得することが簡単になります。
1127 たとえば、クエリの結果をページに分けて出力する場合などに便利です。
1131 <classname>Zend_Db_Select</classname> では、<methodname>limit()</methodname>
1132 メソッドを使用して結果の行数および読み飛ばしの行数を指定します。
1133 このメソッドの<emphasis>最初</emphasis>の引数は取得したい行数、
1134 そして<emphasis>二番目</emphasis>の引数は読み飛ばす行数となります。
1137 <example id="zend.db.select.building.limit.example">
1139 <title>limit() メソッドの例</title>
1141 <programlisting language="php"><![CDATA[
1142 // できあがるクエリは、このようになります
1143 // SELECT p."product_id", p."product_name"
1144 // FROM "products" AS p
1147 // SELECT p."product_id", p."product_name"
1148 // FROM "products" AS p
1149 // LIMIT 20 OFFSET 10
1150 $select = $db->select()
1151 ->from(array('p' => 'products'),
1152 array('product_id', 'product_name'))
1154 ]]></programlisting>
1161 <constant>LIMIT</constant> 構文は、すべての <acronym>RDBMS</acronym>
1162 でサポートされているわけではありません。<acronym>RDBMS</acronym> によっては、
1163 似た機能を別の構文でサポートしているものもあります。
1164 各 <classname>Zend_Db_Adapter_Abstract</classname> クラスには、
1165 その <acronym>RDBMS</acronym> に対応した適切な <acronym>SQL</acronym> を作成するメソッドが用意されています。
1171 一方、<methodname>limitPage()</methodname> メソッドを用いることによっても行数とオフセットを指定できます。
1172 このメソッドは、クエリの結果セット全体から特定の箇所の連続した行のみを取得するものです。
1173 つまり、結果の「ページ」を指定することで、
1174 そのページに該当する部分の結果のみを取得するというわけです。
1175 <methodname>limitPage()</methodname> メソッドの最初の引数にページ数、
1176 2 番目の引数にページあたりの行数を指定します。
1177 どちらの引数も必須で、デフォルト値はありません。
1180 <example id="zend.db.select.building.limit.example2">
1182 <title>limitPage() メソッドの例</title>
1184 <programlisting language="php"><![CDATA[
1185 // できあがるクエリは、このようになります
1186 // SELECT p."product_id", p."product_name"
1187 // FROM "products" AS p
1190 $select = $db->select()
1191 ->from(array('p' => 'products'),
1192 array('product_id', 'product_name'))
1194 ]]></programlisting>
1200 <sect3 id="zend.db.select.building.distinct">
1202 <title>クエリ修飾子 DISTINCT の追加</title>
1205 <methodname>distinct()</methodname> メソッドを使用すると、<acronym>SQL</acronym> クエリに
1206 <constant>DISTINCT</constant> キーワードを追加できます。
1209 <example id="zend.db.select.building.distinct.example">
1211 <title>distinct() メソッドの例</title>
1213 <programlisting language="php"><![CDATA[
1214 // できあがるクエリは、このようになります
1215 // SELECT DISTINCT p."product_name"
1216 // FROM "products" AS p
1218 $select = $db->select()
1220 ->from(array('p' => 'products'), 'product_name');
1221 ]]></programlisting>
1227 <sect3 id="zend.db.select.building.for-update">
1229 <title>クエリ修飾子 FOR UPDATE の追加</title>
1232 <methodname>forUpdate()</methodname> メソッドを使用すると、<acronym>SQL</acronym> クエリに
1233 <code>FOR UPDATE</code> 修飾子を追加できます。
1236 <example id="zend.db.select.building.for-update.example">
1238 <title>forUpdate() メソッドの例</title>
1240 <programlisting language="php"><![CDATA[
1241 // できあがるクエリは、このようになります
1242 // SELECT FOR UPDATE p.*
1243 // FROM "products" AS p
1245 $select = $db->select()
1247 ->from(array('p' => 'products'));
1248 ]]></programlisting>
1254 <sect3 id="zend.db.select.building.union">
1255 <title>UNION クエリの構築</title>
1258 <methodname>union()</methodname>メソッドに<classname>Zend_Db_Select</classname>の配列、
1259 または SQL クエリ文字列を渡すことによって、
1260 <classname>Zend_Db_Select</classname>で結合クエリを構築できます。
1261 どの種類の結合を実行したいか指定するために、
1262 第2引数として、<constant>Zend_Db_Select::SQL_UNION</constant>、
1263 または<constant>Zend_Db_Select::SQL_UNION_ALL</constant>定数を渡せます。
1266 <example id="zend.db.select.building.union.example">
1267 <title>union() メソッド例</title>
1269 <programlisting language="php"><![CDATA[
1270 $sql1 = $db->select();
1271 $sql2 = "SELECT ...";
1273 $select = $db->select()
1274 ->union(array($sql1, $sql2))
1276 ]]></programlisting>
1282 <sect2 id="zend.db.select.execute">
1284 <title>Select クエリの実行</title>
1287 この節では、<classname>Zend_Db_Select</classname> オブジェクトが表すクエリを実行する方法を説明します。
1290 <sect3 id="zend.db.select.execute.query-adapter">
1292 <title>Db アダプタからの Select クエリの実行</title>
1295 <classname>Zend_Db_Select</classname> オブジェクトが表すクエリを実行するには、それを
1296 <classname>Zend_Db_Adapter_Abstract</classname> オブジェクトの <methodname>query()</methodname>
1297 メソッドの最初の引数として渡します。すると、
1298 文字列のクエリのかわりに <classname>Zend_Db_Select</classname> オブジェクトを使用するようになります。
1302 <methodname>query()</methodname> メソッドは、アダプタの型によって
1303 <classname>Zend_Db_Statement</classname> あるいは PDOStatement
1307 <example id="zend.db.select.execute.query-adapter.example">
1309 <title>Db アダプタの query() メソッドの使用例</title>
1311 <programlisting language="php"><![CDATA[
1312 $select = $db->select()
1315 $stmt = $db->query($select);
1316 $result = $stmt->fetchAll();
1317 ]]></programlisting>
1323 <sect3 id="zend.db.select.execute.query-select">
1325 <title>オブジェクトからの Select クエリの実行</title>
1328 アダプタオブジェクトの <methodname>query()</methodname>
1329 メソッドを使用する以外の方法としては、<classname>Zend_Db_Select</classname>
1330 オブジェクトの <methodname>query()</methodname>
1332 どちらのメソッドも、アダプタの型によって
1333 <classname>Zend_Db_Statement</classname> あるいは PDOStatement
1337 <example id="zend.db.select.execute.query-select.example">
1339 <title>Select オブジェクトの query メソッドの使用例</title>
1341 <programlisting language="php"><![CDATA[
1342 $select = $db->select()
1345 $stmt = $select->query();
1346 $result = $stmt->fetchAll();
1347 ]]></programlisting>
1353 <sect3 id="zend.db.select.execute.tostring">
1355 <title>Select オブジェクトから SQL 文字列への変換</title>
1358 <classname>Zend_Db_Select</classname> オブジェクトに対応する
1359 <acronym>SQL</acronym> クエリ文字列にアクセスしたい場合は、
1360 <methodname>__toString()</methodname> メソッドを使用します。
1363 <example id="zend.db.select.execute.tostring.example">
1365 <title>__toString() メソッドの例</title>
1367 <programlisting language="php"><![CDATA[
1368 $select = $db->select()
1371 $sql = $select->__toString();
1374 // 出力は、次のような文字列になります
1375 // SELECT * FROM "products"
1376 ]]></programlisting>
1384 <sect2 id="zend.db.select.other">
1386 <title>その他のメソッド</title>
1389 この節では、これまでにあげてこなかった <classname>Zend_Db_Select</classname>
1390 クラスのメソッドである <methodname>getPart()</methodname> および
1391 <methodname>reset()</methodname> について説明します。
1394 <sect3 id="zend.db.select.other.get-part">
1396 <title>Select オブジェクトの一部の取得</title>
1399 <methodname>getPart()</methodname> メソッドは、<acronym>SQL</acronym> クエリの一部を返します。
1401 <constant>WHERE</constant> 句の式を表す配列や
1402 <constant>SELECT</constant> するカラム (あるいは式) の配列、または
1403 <constant>LIMIT</constant> 句のカウントやオフセットを取得できます。
1407 返り値は、<acronym>SQL</acronym> の一部を抜き取った文字列ではありません。
1408 オブジェクトでの内部表現で、通常は値と式を含む配列となります。
1409 クエリの各部分によって、その構造は異なります。
1413 <methodname>getPart()</methodname> メソッドの引数はひとつで、
1414 Select クエリのどの部分を返すのかをここで指定します。
1415 たとえば、文字列 <code>'from'</code> を指定すると、
1416 Select オブジェクトが <constant>FROM</constant>
1417 句として保持しているテーブルの情報を返します。
1418 ここには結合している他のテーブルも含まれます。
1422 <classname>Zend_Db_Select</classname> クラスでは、<acronym>SQL</acronym> クエリの各部分を指定するための定数を定義しています。
1423 これらの定数、あるいはリテラル文字列のいずれかで指定できます。
1426 <table id="zend.db.select.other.get-part.table">
1428 <title>getPart() および reset() で使用する定数</title>
1440 <entry><constant>Zend_Db_Select::DISTINCT</constant></entry>
1441 <entry><code>'distinct'</code></entry>
1445 <entry><constant>Zend_Db_Select::FOR_UPDATE</constant></entry>
1446 <entry><code>'forupdate'</code></entry>
1450 <entry><constant>Zend_Db_Select::COLUMNS</constant></entry>
1451 <entry><code>'columns'</code></entry>
1455 <entry><constant>Zend_Db_Select::FROM</constant></entry>
1456 <entry><code>'from'</code></entry>
1460 <entry><constant>Zend_Db_Select::WHERE</constant></entry>
1461 <entry><code>'where'</code></entry>
1465 <entry><constant>Zend_Db_Select::GROUP</constant></entry>
1466 <entry><code>'group'</code></entry>
1470 <entry><constant>Zend_Db_Select::HAVING</constant></entry>
1471 <entry><code>'having'</code></entry>
1475 <entry><constant>Zend_Db_Select::ORDER</constant></entry>
1476 <entry><code>'order'</code></entry>
1480 <entry><constant>Zend_Db_Select::LIMIT_COUNT</constant></entry>
1481 <entry><code>'limitcount'</code></entry>
1485 <entry><constant>Zend_Db_Select::LIMIT_OFFSET</constant></entry>
1486 <entry><code>'limitoffset'</code></entry>
1492 <example id="zend.db.select.other.get-part.example">
1494 <title>getPart() メソッドの例</title>
1496 <programlisting language="php"><![CDATA[
1497 $select = $db->select()
1499 ->order('product_id');
1501 // 文字列リテラルを使用して指定できます
1502 $orderData = $select->getPart( 'order' );
1504 // 同じことを、定数を用いて指定することもできます
1505 $orderData = $select->getPart( Zend_Db_Select::ORDER );
1507 // 返り値は、文字列ではなく配列となります。
1508 // 各部分が異なる構造になっています。
1509 print_r( $orderData );
1510 ]]></programlisting>
1516 <sect3 id="zend.db.select.other.reset">
1518 <title>Select オブジェクトの一部のリセット</title>
1521 <methodname>reset()</methodname> メソッドを使用すると、
1522 <acronym>SQL</acronym> クエリの指定した部分のみを消去できます。
1523 引数を省略した場合は、すべての部分を消去します。
1528 消去したい <acronym>SQL</acronym> の部分を、<methodname>getPart()</methodname>
1529 メソッドの引数と同じ文字列で指定します。
1530 クエリの指定した部分が、デフォルトの状態に戻ります。
1534 パラメータを省略すると、<methodname>reset()</methodname>
1535 はクエリのすべての部分をデフォルトの状態に戻します。
1536 これにより、<classname>Zend_Db_Select</classname> オブジェクトは初期状態と同等になります。
1537 つまり、最初にインスタンスを作成したときと同じ状態ということです。
1540 <example id="zend.db.select.other.reset.example">
1542 <title>reset() メソッドの例</title>
1544 <programlisting language="php"><![CDATA[
1545 // できあがるクエリは、このようになります
1547 // FROM "products" AS p
1548 // ORDER BY "product_name"
1550 $select = $db->select()
1551 ->from(array('p' => 'products')
1552 ->order('product_name');
1554 // 条件を変更し、別のカラムで並べ替えます
1556 // FROM "products" AS p
1557 // ORDER BY "product_id"
1559 // 再定義するため、いちどこの部分を消去します
1560 $select->reset( Zend_Db_Select::ORDER );
1563 $select->order('product_id');
1567 ]]></programlisting>
1577 vim:se ts=4 sw=4 et: