| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552 |
- <sect1 id="zend.db.select">
- <title>Zend_Db_Select</title>
- <sect2 id="zend.db.select.introduction">
- <title>Обзор</title>
- <para>
- Объект Zend_Db_Select представляет SQL-оператор <code>SELECT</code>.
- Класс имеет методы для добавления отдельных частей запроса. Вы
- можете определять некоторые части запроса, используя методы PHP и
- структуры данных, и класс формирует корректный синтаксис SQL.
- После того, как построен запрос, можно выполнять его так же, как
- если бы он был написан в виде строки.
- </para>
- <para>
- В число достоинств Zend_Db_Select входит:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Объектно-ориентированные методы для "покусочного" построения
- SQL-запросов;
- </para>
- </listitem>
- <listitem>
- <para>
- Не зависящая от типа БД абстракция некоторых частей
- SQL-запроса;
- </para>
- </listitem>
- <listitem>
- <para>
- Автоматическое в большинстве случаев заключение в кавычки
- идентификаторов метаданных для поддержки
- идентификаторов, содержащих зарезервированные SQL слова и
- спецсимволы;
- </para>
- </listitem>
- <listitem>
- <para>
- Заключение в кавычки идентификаторов и значений для снижения
- угрозы атак с использованием SQL-инъекций.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Использование Zend_Db_Select не обязательно. Для очень простых
- запросов SELECT обычно проще указать SQL-запрос целиком в виде
- строки и выполнить его, используя такие методы адаптера, как
- <code>query()</code> или <code>fetchAll()</code>. Использование
- Zend_Db_Select полезно, если нужно собрать запрос SELECT в процессе
- или основываясь на условной логике.
- </para>
- </sect2>
- <sect2 id="zend.db.select.creating">
- <title>Создание объекта Select</title>
- <para>
- Вы можете создавать экземпляр объекта Zend_Db_Select, используя
- метод <code>select()</code> объекта Zend_Db_Adapter_Abstract.
- </para>
- <example id="zend.db.select.creating.example-db">
- <title>Пример использования метода select() адаптера БД</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory( ...опции... );
- $select = $db->select();
- ]]>
- </programlisting>
- </example>
- <para>
- Другой способ состоит в создании объекта Zend_Db_Select через
- конструктор, при этом в качестве аргумента указывается адаптер БД.
- </para>
- <example id="zend.db.select.creating.example-new">
- <title>Пример создания нового объекта Select</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory( ...опции... );
- $select = new Zend_Db_Select($db);
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.select.building">
- <title>Построение запросов Select</title>
- <para>
- При построении запроса вы можете добавлять по одному его
- предложения. Предложение - это часть SQL-оператора, не
- представляющая собой законченный оператор; например, предложение
- WHERE. Для каждого предложения есть свой метод Zend_Db_Select.
- </para>
- <example id="zend.db.select.building.example">
- <title>Пример использования методов для добавления предложений</title>
- <programlisting language="php"><![CDATA[
- // Создание объекта Zend_Db_Select
- $select = $db->select();
- // Добавление предложения FROM
- $select->from( ...определение таблицы и столбцов... )
- // Добавление предложения WHERE
- $select->where( ...определение критериев поиска... )
- // Добавление предложения ORDER BY
- $select->order( ...определение критериев сортировки... );
- ]]>
- </programlisting>
- </example>
- <para>
- Вы также можете использовать большинство методов объекта
- Zend_Db_Select в так называемом fluent interface.
- Fluent interface означает, что каждый метод возвращает ссылку на
- тот объект, в котором он был вызван, поэтому вы можете вызывать
- другой метод непосредственно за ним.
- </para>
- <example id="zend.db.select.building.example-fluent">
- <title>Пример использования fluent interface</title>
- <programlisting language="php"><![CDATA[
- $select = $db->select()
- ->from( ...определение таблицы и столбцов... )
- ->where( ...определение критериев поиска... )
- ->order( ...определение критериев сортировки... );
- ]]>
- </programlisting>
- </example>
- <para>
- Этот пример демонстрирует применение fluent interface, но в любом
- случае вы можете использовать стандартный подход. Часто
- бывает необходимо использовать стандартный подход - например, когда
- нужно выполнить некоторую логику до добавления предложения в запрос.
- </para>
- <sect3 id="zend.db.select.building.from">
- <title>Добавление предложения FROM</title>
- <para>
- Указывайте таблицу для запроса, используя метод
- <code>from()</code>. Вы можете задавать имя таблицы в виде
- простой строки, Zend_Db_Select добавит идентификатор, заключив в
- кавычки имя таблицы, поэтому вы можете использовать специальные
- символы.
- </para>
- <example id="zend.db.select.building.from.example">
- <title>Пример использования метода from()</title>
- <programlisting language="php">
- <![CDATA[
- // Строит запрос:
- // SELECT *
- // FROM "products"
- $select = $db->select()
- ->from( 'products' );
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете также задавать корреляционное (называемое также
- "псевдонимом") имя таблицы. В этом случае вместо простой строки
- используйте ассоциативный массив корреляционных имен и
- действительных имен таблиц. В других предложениях SQL-запроса
- используйте это корреляционное имя. Если в вашем запросе
- объединяется более одной таблицы, то Zend_Db_Select генерирует
- уникальные корреляционные имена, основанные на именах таблиц,
- для всех таблиц, для которых не были заданы корреляционные
- имена.
- </para>
- <example id="zend.db.select.building.from.example-cname">
- <title>Пример задания корреляционного имени таблицы</title>
- <programlisting language="php">
- <![CDATA[
- // Строит запрос:
- // SELECT p.*
- // FROM "products" AS p
- $select = $db->select()
- ->from( array('p' => 'products') );
- ]]>
- </programlisting>
- </example>
- <para>
- Некоторые СУРБД поддерживают спецификатор схемы для таблицы. Вы
- можете задавать имя таблицы в виде
- "<code>имяСхемы.имяТаблицы</code>". Zend_Db_Select заключит в
- кавычки все части по отдельности.
- </para>
- <example id="zend.db.select.building.from.example-schema">
- <title>Пример задания имени схемы</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT *
- // FROM "myschema"."products"
- $select = $db->select()
- ->from( 'myschema.products' );
- // или
- $select = $db->select()
- ->from('products', '*', 'myschema');
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.columns">
- <title>Добавление колонок</title>
- <para>
- Во втором аргументе метода <code>from()</code> вы можете
- задавать столбцы для выборки из соответствующей таблицы. Если вы
- не укажете столбцы для выборки, то по умолчанию будет подставлен
- метасимвол "<code>*</code>", означающий "все столбцы".
- </para>
- <para>
- Вы можете перечислить столбцы в простом массиве строк или
- в ассоциативном массиве псевдонимов столбцов и их имен. Если в
- запросе нужен только один столбец, и к нему не нужен псевдоним,
- то можно передать строку с его именем вместо массива.
- </para>
- <para>
- Если вы передали пустой массив в качестве аргумента для
- столбцов, то ни один столбец из соответствующей таблицы не будет
- включен в результат выборки. См.
- <link linkend="zend.db.select.building.join.example-no-columns">пример
- кода</link> в разделе про метод <code>join()</code>.
- </para>
- <para>
- Вы можете указать имя столбца как
- "<code>корреляционноеИмя.имяСтолбца</code>". Zend_Db_Select
- заключит в кавычки все части по отдельности. Если вы не укажете
- корреляционное имя для столбца, то используется корреляционное
- имя таблицы, указанной в текущем вызове метода
- <code>from()</code>.
- </para>
- <example id="zend.db.select.building.columns.example">
- <title>Пример указания столбцов</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'product_name'));
- // Строит тот же запрос с указанием корреляционных имен:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('p.product_id', 'p.product_name'));
- // Строит тот же запрос с псевдонимом для одного столбца:
- // SELECT p."product_id" AS prodno, p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('prodno' => 'product_id', 'product_name'));
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.columns-expr">
- <title>Добавление столбцов выражений</title>
- <para>
- Столбцы в SQL-запросах иногда представляют собой выражения, а не
- просто столбцы из таблицы. Выражения не должны иметь
- корреляционные имена и заключаться в кавычки. Если строка,
- обозначающая столбец запроса, содержит скобки, то Zend_Db_Select
- распознает ее как выражение.
- </para>
- <para>
- Вы можете также явно создавать объект типа Zend_Db_Expr для
- того, чтобы предотвратить ошибочное распознавание строки как
- имени столбца. Zend_Db_Expr - мини-класс, содержащий
- только строку. Zend_Db_Select распознает объекты типа
- Zend_Db_Expr и преобразует их обратно в строку, но без таких
- действий, как заключение в кавычки и добавление корелляционных
- имен.
- </para>
- <note>
- <para>
- Использование Zend_Db_Expr не обязательно, если ваше
- выражение содержит скобки. Zend_Db_Select распознает
- выражение по скобкам и оперирует строкой как выражением,
- пропуская такие действия, как заключение в кавычки и
- добавление корреляционных имен.
- </para>
- </note>
- <example id="zend.db.select.building.columns-expr.example">
- <title>Пример указания столбцов, содержащих выражения</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", LOWER(product_name)
- // FROM "products" AS p
- // Выражение со скобками неявно преобразуется в Zend_Db_Expr.
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'LOWER(product_name)'));
- // Строит запрос:
- // SELECT p."product_id", (p.cost * 1.08) AS cost_plus_tax
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id',
- 'cost_plus_tax' => '(p.cost * 1.08)')
- );
- // Построение того же запроса с явным использованием Zend_Db_Expr:
- // SELECT p."product_id", p.cost * 1.08 AS cost_plus_tax
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id',
- 'cost_plus_tax' =>
- new Zend_Db_Expr('p.cost * 1.08'))
- );
- ]]>
- </programlisting>
- </example>
- <para>
- В примерах выше Zend_Db_Select не модифицирует строку для
- добавления корреляционных имен или заключения идентификаторов в
- кавычки. Если эти изменения необходимы для исключения
- неоднозначности, то вы должны произвести их в строке вручную.
- </para>
- <para>
- Если имена столбцов являются ключевыми словами SQL или содержат
- специальные символы, то следует использовать метод адаптера
- <code>quoteIdentifier()</code> и включать результат в строку.
- Метод <code>quoteIdentifier()</code> использует заключение в
- кавычки для ограничения идентификатора, тем самым обозначается,
- что это идентификатор таблицы или столбца, а не другая часть
- синтаксиса SQL.
- </para>
- <para>
- Ваш код будет более независимым от типа БД, если вы будете
- использовать метод <code>quoteIdentifier()</code> вместо
- непосредственного добавления кавычек в строке, поскольку
- некоторые БД используют нестандартные символы вместо кавычек.
- Метод <code>quoteIdentifier()</code>
- использует нужные символы, основываясь на типе
- адаптера. <code>quoteIdentifier()</code> также экранирует
- символы кавычек в самом идентификаторе.
- </para>
- <example id="zend.db.select.building.columns-quoteid.example">
- <title>Пример заключения в кавычки столбцов в выражении</title>
- <programlisting language="php"><![CDATA[
- // Строится следующий запрос, при этом имя столбца "from" в выражении
- // заключается в кавычки:
- // SELECT p."from" + 10 AS origin
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('origin' =>
- '(p.' . $db->quoteIdentifier('from') . ' + 10)')
- );
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.columns-atomic">
- <title>Добавление столбцов в существующую таблицу FROM или JOIN</title>
- <para>
- Может потребоваться добавить столбцы в таблицу FROM или JOIN
- после того, как были вызваны соответствующие методы. Метод
- <code>columns()</code> позволяет добавлять определенные столбцы
- в любой момент до того, как будет выполнен запрос. Вы можете
- передавать столбцы в виде строки, объекта
- <code>Zend_Db_Expr</code> или массива этих элементов. Второй
- аргумент этого метода может быть опущен, это значит, что столбцы
- должны быть добавлены в таблицу FROM, иначе должно
- использоваться существующее корреляционное имя.
- </para>
- <example id="zend.db.select.building.columns-atomic.example">
- <title>Пример добавления столбцов через метод <code>columns()</code></title>
- <programlisting language="php"><![CDATA[
- // Строится следующий запрос:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'), 'product_id')
- ->columns('product_name');
- // Строится тот же запрос с указанием корреляционных имен:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->from(array('p' => 'products'), 'p.product_id')
- ->columns('product_name', 'p');
- // Можно также писать: columns('p.product_name')]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.join">
- <title>Добавление в запрос другой таблицы c помощью JOIN</title>
- <para>
- Многие полезные запросы используют <code>JOIN</code> для
- объединения строк из разных таблиц. Вы можете добавлять таблицы
- в запрос, используя метод <code>join()</code> объекта
- Zend_Db_Select. Использование этого метода похоже на
- использование <code>from()</code> за тем исключением, что в
- большинстве случаев вам нужно будет также указать условие
- объединения.
- </para>
- <example id="zend.db.select.building.join.example">
- <title>Пример использования метода join()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", p."product_name", l.*
- // FROM "products" AS p JOIN "line_items" AS l
- // ON p.product_id = l.product_id
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'product_name'))
- ->join(array('l' => 'line_items'),
- 'p.product_id = l.product_id');
- ]]>
- </programlisting>
- </example>
- <para>
- Второй аргумент метода <code>join()</code> является строкой,
- содержащей условие объединения. Это выражение объявляет условие,
- при выполнении которого строки в одной таблице объединяются со
- сроками в другой таблице. Вы можете использовать корреляционные
- имена в этом выражении.
- </para>
- <note>
- <para>
- К выражению, указанному вами как условие объединения, не
- применяется автоматическое заключение в кавычки. Если нужно
- заключить в кавычки имена столбцов, то используйте
- <code>quoteIdentifier()</code> при формировании строки
- условия объединения.
- </para>
- </note>
- <para>
- Третий аргумент метода <code>join()</code> - массив имен
- столбцов, как и в методе <code>from()</code>. По умолчанию
- используется "<code>*</code>" вместо столбцов,
- поддерживаются корреляционные имена, выражения и Zend_Db_Expr -
- так же, как и в случае массива столбцов для метода
- <code>from()</code>.
- </para>
- <para>
- Если из таблицы не нужно выбирать столбцы, то используйте пустой
- массив вместо перечисления столбцов. Это работает и для метода
- <code>from()</code>, но обычно требуется извлечь часть столбцов
- из основной таблицы в запросе, при этом может не требоваться
- получение столбцов из присоединяемой таблицы.
- </para>
- <example id="zend.db.select.building.join.example-no-columns">
- <title>Пример извлечения без столбцов</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p JOIN "line_items" AS l
- // ON p.product_id = l.product_id
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'product_name'))
- ->join(array('l' => 'line_items'),
- 'p.product_id = l.product_id',
- array() ); // empty list of columns
- ]]>
- </programlisting>
- <para>
- Обратите внимание на пустой <code>array()</code> в примере
- выше вместо списка столбцов из присоединяемой таблицы.
- </para>
- </example>
- <para>
- SQL имеет несколько типов объединений. Ниже приведен список
- методов для поддержки различных типов объединений в
- Zend_Db_Select.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <command>INNER JOIN</command>, методы
- <code>join(table, join, [columns])</code>
- и <code>joinInner(table, join, [columns])</code>.
- </para>
- <para>
- Возможно, наиболее часто используемый тип объединения.
- Строки из каждой таблицы сравниваются с
- использованием условия сравнения. Результат включает в
- себя только те строки, которые удовлетворяют условию
- объединения. Результат может быть пустым, если ни одна
- строка не удовлетворяет этому условию.
- </para>
- <para>
- Все СУРБД поддерживают этот тип объединения.
- </para>
- </listitem>
- <listitem>
- <para>
- <command>LEFT JOIN</command>, метод <code>joinLeft(table, condition, [columns])</code>.
- </para>
- <para>
- В результат входят все строки из таблицы слева и все
- соответствующие строки из таблицы справа. Если нет
- соответствующих строк из таблицы справа, то
- соответствующие столбцы в результате заполняются NULL.
- </para>
- <para>
- Все СУРБД поддерживают этот тип объединения.
- </para>
- </listitem>
- <listitem>
- <para>
- <command>RIGHT JOIN</command>, метод <code>joinRight(table, condition, [columns])</code>.
- </para>
- <para>
- Правое внешнее объединение дополняет левое внешнее
- объединение. В результат входят все строки из таблицы
- справа и все соответствующие строки из таблицы слева.
- Если нет соответствующих строк из таблицы слева, то
- соответствующие столбцы в результате заполняются NULL.
- </para>
- <para>
- Некоторые СУРБД не поддерживают этот тип объединения,
- но, как правило, любое правое объединение может быть
- заменено на левое посредством изменения порядка таблиц
- на обратный.
- </para>
- </listitem>
- <listitem>
- <para>
- <command>FULL JOIN</command>, метод
- <code>joinFull(table, condition, [columns])</code>.
- </para>
- <para>
- Полное внешнее объединение является как бы комбинацией
- левого и правого объединений. Все строки из обоих таблиц
- входят в результат, при этом объединяются друг с другом
- в одну строку результата, если соответствуют условию
- объединения, иначе объединяются с NULL вместо значений
- столбцов из другой таблицы.
- </para>
- <para>
- Некоторые СУРБД не поддерживают этот тип объединения.
- </para>
- </listitem>
- <listitem>
- <para>
- <command>CROSS JOIN</command>, метод
- <code>joinCross(table, [columns])</code>.
- </para>
- <para>
- Перекрестное объединение является декартовым
- произведением. Каждая строка в первой таблице
- объединяется с со всеми строками во второй таблице.
- Таким образом, количество строк в результате будет равно
- произведению числа строк в обоих таблицах. Вы можете
- фильтровать результат, используя условие в предложении
- WHERE, в этом случае перекрестное объединение подобно
- старому синтаксису объединений в SQL-89.
- </para>
- <para>
- Метод <code>joinCross()</code> не имеет параметров для
- определения условий объединения. Некоторые СУРБД не
- поддерживают этот тип объединения.
- </para>
- </listitem>
- <listitem>
- <para>
- <command>NATURAL JOIN</command>, метод
- <code>joinNatural(table, [columns])</code>.
- </para>
- <para>
- Естественное объединение сравнивает столбцы, имеющие
- одинаковые имена в обоих таблицах. Проверка производится
- на равенство; проверка на неравенство не является
- естественным объединением.
- Данным API поддерживаются только внутренние
- естественные объединения, даже если SQL поддерживает
- внешние естественные объединения.
- </para>
- <para>
- Метод <code>joinNatural()</code> не имеет параметров для
- определения условий объединения.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- В дополнение к этим методам объединения вы можете упростить свои
- запросы, используя методы JoinUsing. Вместо предоставления
- полного условия объединения вы можете просто передавать имя
- столбца, по которому производится объединение, и Zend_Db_Select
- допишет условие объединения за вас.
- </para>
- <example id="zend.db.select.building.joinusing.example">
- <title>Пример использования метода joinUsing()</title>
- <programlisting language="php"><![CDATA[
- // Строится запрос:
- // SELECT *
- // FROM "table1"
- // JOIN "table2"
- // ON "table1".column1 = "table2".column1
- // WHERE column2 = 'foo'
- $select = $db->select()
- ->from('table1')
- ->joinUsing('table2', 'column1')
- ->where('column2 = ?', 'foo');]]>
- </programlisting>
- </example>
- <para>
- Каждый метод объединения из перечисленных выше имеет соответствующий ему метод JoinUsing.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>joinUsing(table, join, [columns])</code> и
- <code>joinInnerUsing(table, join, [columns])</code>
- </para>
- </listitem>
- <listitem>
- <para>
- <code>joinLeftUsing(table, join, [columns])</code>
- </para>
- </listitem>
- <listitem>
- <para>
- <code>joinRightUsing(table, join, [columns])</code>
- </para>
- </listitem>
- <listitem>
- <para>
- <code>joinFullUsing(table, join, [columns])</code>
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.select.building.where">
- <title>Добавление предложения WHERE</title>
- <para>
- Вы можете задавать условия для ограничения строк в результате
- выборки, используя метод <code>where()</code>. Первым аргументом
- этого метода является SQL-выражение, которое используется в
- предложении <code>WHERE</code> в данном запросе.
- </para>
- <example id="zend.db.select.building.where.example">
- <title>Пример использования метода where()</title>
- <programlisting language="php"><![CDATA[
- // Строится запрос:
- // SELECT product_id, product_name, price
- // FROM "products"
- // WHERE price > 100.00
- $select = $db->select()
- ->from('products',
- array('product_id', 'product_name', 'price'))
- ->where('price > 100.00');]]>
- </programlisting>
- </example>
- <note>
- <para>
- К выражениям для методов <code>where()</code> или
- <code>orWhere()</code> не применяется автоматическое
- заключение в кавычки. Если необходимо, чтобы имена столбцов
- были заключены в кавычки, то используйте метод
- <code>quoteIdentifier()</code> при формировании строки
- условия.
- </para>
- </note>
- <para>
- Второй аргумент метода <code>where()</code> является
- опциональным. Это значение подставляется в выражение.
- Zend_Db_Select заключает это значение в кавычки и подставляет
- вместо знака вопроса ("<code>?</code>") в выражении.
- </para>
- <para>
- Этот метод принимает только один параметр. Если в выражение
- подставляется несколько значений, то нужно сформировать строку
- вручную, вставляя переменные и заключая их в кавычки
- самостоятельно.
- </para>
- <example id="zend.db.select.building.where.example-param">
- <title>Пример параметра в методе where()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT product_id, product_name, price
- // FROM "products"
- // WHERE (price > 100.00)
- $minimumPrice = 100;
- $select = $db->select()
- ->from('products',
- array('product_id', 'product_name', 'price'))
- ->where('price > ?', $minimumPrice);
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете вызывать метод <code>where()</code> несколько раз на
- одном и том же объекте Zend_Db_Select. Результирующий запрос
- объединяет в себе все термы с добавлением <code>AND</code>
- между ними.
- </para>
- <example id="zend.db.select.building.where.example-and">
- <title>Пример нескольких вызовов метода where()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT product_id, product_name, price
- // FROM "products"
- // WHERE (price > 100.00)
- // AND (price < 500.00)
- $minimumPrice = 100;
- $maximumPrice = 500;
- $select = $db->select()
- ->from('products',
- array('product_id', 'product_name', 'price'))
- ->where('price > ?', $minimumPrice)
- ->where('price < ?', $maximumPrice);
- ]]>
- </programlisting>
- </example>
- <para>
- Если вам нужно объединить термы с использованием
- <code>OR</code>, то используйте метод <code>orWhere()</code>.
- Этот метод используется так же, как и метод
- <code>where()</code>, за тем исключением, что определенный в
- этом вызове терм добавляется вместе с <code>OR</code> вместо
- <code>AND</code>.
- </para>
- <example id="zend.db.select.building.where.example-or">
- <title>Пример использования метода orWhere()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT product_id, product_name, price
- // FROM "products"
- // WHERE (price < 100.00)
- // OR (price > 500.00)
- $minimumPrice = 100;
- $maximumPrice = 500;
- $select = $db->select()
- ->from('products',
- array('product_id', 'product_name', 'price'))
- ->where('price < ?', $minimumPrice)
- ->orWhere('price > ?', $maximumPrice);
- ]]>
- </programlisting>
- </example>
- <para>
- Zend_Db_Select автоматически заключает в скобки все выражения,
- которые вы добавляете через методы <code>where()</code> или
- <code>orWhere()</code>. Это позволяет быть уверенным в том, что
- приоритет булевых операторов не приведет к другому результату
- вместо ожидаемого.
- </para>
- <example id="zend.db.select.building.where.example-parens">
- <title>Пример заключения булевых выражений в скобки</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT product_id, product_name, price
- // FROM "products"
- // WHERE (price < 100.00 OR price > 500.00)
- // AND (product_name = 'Apple')
- $minimumPrice = 100;
- $maximumPrice = 500;
- $prod = 'Apple';
- $select = $db->select()
- ->from('products',
- array('product_id', 'product_name', 'price'))
- ->where("price < $minimumPrice OR price > $maximumPrice")
- ->where('product_name = ?', $prod);
- ]]>
- </programlisting>
- </example>
- <para>
- В примере выше результаты могут отличаться от тех, что
- получаются без скобок, потому что <code>AND</code> имеет больший
- приоритет, чем <code>OR</code>. Zend_Db_Select добавляет скобки,
- Таким образом, результатом является то, что каждое выражение,
- добавленное в успешных вызовах <code>where()</code> более
- связанно, чем <code>AND</code>, объединяющее эти выражения.
- </para>
- </sect3>
- <sect3 id="zend.db.select.building.group">
- <title>Добавление предложения GROUP BY</title>
- <para>
- В языке SQL выражение <code>GROUP BY</code> позволяет ограничить
- количество строк в результатах запроса до одной стоки на каждое
- уникальное значение в столбцах, перечисленных в предложении
- <code>GROUP BY</code>.
- </para>
- <para>
- В Zend_Db_Select вы можете задавать столбцы, используемые для
- определения групп строк, через метод <code>group()</code>.
- Аргументом этого метода является столбец или массив столбцов для
- подстановки в предложение <code>GROUP BY</code>.
- </para>
- <example id="zend.db.select.building.group.example">
- <title>Пример использования метода group()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", COUNT(*) AS line_items_per_product
- // FROM "products" AS p JOIN "line_items" AS l
- // ON p.product_id = l.product_id
- // GROUP BY p.product_id
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id'))
- ->join(array('l' => 'line_items'),
- 'p.product_id = l.product_id',
- array('line_items_per_product' => 'COUNT(*)'))
- ->group('p.product_id');
- ]]>
- </programlisting>
- </example>
- <para>
- Как и для массива столбцов в методе <code>from()</code>, вы
- можете использовать корреляционные имена в именах столбцов,
- столбцы заключаются в кавычки в качестве идентификаторов, если
- строка не содержит скобок или является объектом типа
- Zend_Db_Expr.
- </para>
- </sect3>
- <sect3 id="zend.db.select.building.having">
- <title>Добавление предложения HAVING</title>
- <para>
- В SQL предложение <code>HAVING</code> применяет условие
- ограничения к группам строк. Это подобно тому, как предложение
- <code>WHERE</code> применяет условие ограничения к строкам.
- Но эти предложения не являются идентичными, поскольку условия
- <code>WHERE</code> применяются до группировки, в то время как
- условия <code>HAVING</code> применяется после группировки.
- </para>
- <para>
- В Zend_Db_Select вы можете определять условия ограничения
- групп через метод <code>having()</code>. Его использование
- аналогично использованию метода <code>where()</code>. Первый
- аргумент является строкой, содержащей SQL-выражение.
- Опциональный второй аргумент - значение, которое используется
- для подстановки вместо метки заполнения в SQL-выражении.
- Выражения, переданные в нескольких вызовах метода
- <code>having()</code>, объединяются через булевый оператор
- <code>AND</code> или через булевый оператор
- <code>OR</code>, если вы используете метод
- <code>orHaving()</code>.
- </para>
- <example id="zend.db.select.building.having.example">
- <title>Пример использования метода having()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", COUNT(*) AS line_items_per_product
- // FROM "products" AS p JOIN "line_items" AS l
- // ON p.product_id = l.product_id
- // GROUP BY p.product_id
- // HAVING line_items_per_product > 10
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id'))
- ->join(array('l' => 'line_items'),
- 'p.product_id = l.product_id',
- array('line_items_per_product' => 'COUNT(*)'))
- ->group('p.product_id')
- ->having('line_items_per_product > 10');
- ]]>
- </programlisting>
- </example>
- <note>
- <para>
- К выражениям, переданным через методы <code>having()</code>
- или <code>orHaving()</code>, не применяется автоматическое
- заключение в кавычки. Если у вас есть имена столбцов,
- которые требуется заключить в кавычки, то используйте
- <code>quoteIdentifier()</code> при формировании строки
- условия.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.select.building.order">
- <title>Добавление предложения ORDER BY</title>
- <para>
- В SQL предложение <code>ORDER BY</code> задает один или более
- столбцов (или выражений), по которым сортируется результат
- запроса. Если перечислено несколько столбцов, то вторичные
- столбцы используются для принятия решения в ситуации "ничьи":
- если первичные столбцы содержат идентичные значения, то порядок
- сортировки определяется через вторичные столбцы. По умолчанию
- сортировка производится от меньших значений к большим. Вы можете
- также производить для данного столбца сортировку от больших
- значений к меньшим, указав ключевое слово <code>DESC</code>
- после этого столбца.
- </para>
- <para>
- В Zend_Db_Select вы можете использовать метод
- <code>order()</code> для определения столбца или массива
- столбцов, по которым производится сортировка. Каждый элемент
- массива является строкой с именем столбца, опционально строка
- может содержать ключевое слово <code>ASC</code> или
- <code>DESC</code> после имени столбца и отделенное от него
- пробелом.
- </para>
- <para>
- Как и в случае методов <code>from()</code> и
- <code>group()</code>, имена столбцов заключаются в кавычки в
- качестве идентификаторов, если они не содержат скобки и не
- являются объектами Zend_Db_Expr.
- </para>
- <example id="zend.db.select.building.order.example">
- <title>Пример использования метода order()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", COUNT(*) AS line_items_per_product
- // FROM "products" AS p JOIN "line_items" AS l
- // ON p.product_id = l.product_id
- // GROUP BY p.product_id
- // ORDER BY "line_items_per_product" DESC, "product_id"
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id'))
- ->join(array('l' => 'line_items'),
- 'p.product_id = l.product_id',
- array('line_items_per_product' => 'COUNT(*)'))
- ->group('p.product_id')
- ->order(array('line_items_per_product DESC',
- 'product_id'));
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.limit">
- <title>Добавление предложения LIMIT</title>
- <para>
- Некоторые СУРБД расширяют язык SQL предложением, известным как
- предложение <code>LIMIT</code>. Это предложение ограничивает
- количество строк в результате запроса до заданного вами
- количества. Вы можете также задать количество пропускаемых до
- начала вывода строк. Эта возможность облегчает выборку
- подмножества строк результата - например, для постраничного
- вывода результатов запроса.
- </para>
- <para>
- В Zend_Db_Select вы можете использовать метод
- <code>limit()</code> для задания количества строк в выборке и
- количества пропускаемых строк. Первым аргументом этого метода
- является желаемое количество строк в результате запроса. Вторым
- аргументом - количество пропускаемых строк
- </para>
- <example id="zend.db.select.building.limit.example">
- <title>Пример использования метода limit()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- // LIMIT 10, 20
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'product_name'))
- ->limit(10, 20);
- ]]>
- </programlisting>
- </example>
- <note>
- <para>
- Ситаксис <code>LIMIT</code> поддерживается не всеми СУРБД.
- Некоторые СУРБД используют другой синтаксис для поддержки
- аналогичной функциональности. Каждый класс
- Zend_Db_Adapter_Abstract включает в себя метод для генерации
- SQL, присущего данной СУРБД.
- </para>
- </note>
- <para>
- Используйте метод <code>limitPage()</code> в качестве
- альтернативного способа указания количества строк и смещения.
- Этот метод позволяет ограничить набор возвращаемых результатов
- подмножеством фиксированной длины, который является одним из
- последовательности подмножеств, составляющих весь набор
- результатов запроса.
- Другими словами, вы указываете длину "страницы" результатов в
- строках и порядковый номер страницы для извлечения. Номер
- страницы является первым аргументом в методе
- <code>limitPage()</code>, а длина страницы - вторым. Оба
- аргумента являются обязательными и не имеют значений по
- умолчанию.
- </para>
- <example id="zend.db.select.building.limit.example2">
- <title>Пример использования метода limitPage()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p."product_id", p."product_name"
- // FROM "products" AS p
- // LIMIT 10, 20
- $select = $db->select()
- ->from(array('p' => 'products'),
- array('product_id', 'product_name'))
- ->limitPage(2, 10);
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.distinct">
- <title>Добавление модификатора DISTINCT</title>
- <para>
- Метод <code>distinct()</code> дает возможность добавлять
- ключевое слово <code>DISTINCT</code> в ваш запрос.
- </para>
- <example id="zend.db.select.building.distinct.example">
- <title>Пример использования метода distinct()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT DISTINCT p."product_name"
- // FROM "products" AS p
- $select = $db->select()
- ->distinct()
- ->from(array('p' => 'products'), 'product_name');
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.building.for-update">
- <title>Добавление модификатора FOR UPDATE</title>
- <para>
- Метод <code>forUpdate()</code> дает возможность добавлять
- модификатор <code>FOR UPDATE</code> в ваш запрос.
- </para>
- <example id="zend.db.select.building.for-update.example">
- <title>Пример использования метода forUpdate()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT FOR UPDATE p.*
- // FROM "products" AS p
- $select = $db->select()
- ->forUpdate()
- ->from(array('p' => 'products'));
- ]]>
- </programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.select.execute">
- <title>Произведение запросов на выборку</title>
- <para>
- Этот раздел объясняет, как производить запрос, представленный
- объектом Zend_Db_Select.
- </para>
- <sect3 id="zend.db.select.execute.query-adapter">
- <title>Произведение запросов на выборку из адаптера БД</title>
- <para>
- Вы можете производить запрос, представленный объектом
- Zend_Db_Select, посредством передачи его в качестве первого
- аргумента методу <code>query()</code> объекта
- Zend_Db_Adapter_Abstract. Используйте объекты Zend_Db_Select
- вместо строк запроса.
- </para>
- <para>
- Метод <code>query()</code> возвращает объект Zend_Db_Statement
- или PDOStatement, в зависимости от типа адаптера.
- </para>
- <example id="zend.db.select.execute.query-adapter.example">
- <title>Пример использования метода query() адаптера БД</title>
- <programlisting language="php"><![CDATA[
- $select = $db->select()
- ->from('products');
- $stmt = $db->query($select);
- $result = $stmt->fetchAll();
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.execute.query-select">
- <title>Произведение запросов на выборку через объект Select</title>
- <para>
- Вместо метода <code>query()</code> объекта адаптера можно
- использовать метод <code>query()</code> объекта Zend_Db_Select.
- Оба метода возвращают объект типа Zend_Db_Statement или
- PDOStatement, в зависимости от типа адаптера.
- </para>
- <example id="zend.db.select.execute.query-select.example">
- <title>Пример использования метода query() объекта Select</title>
- <programlisting language="php"><![CDATA[
- $select = $db->select()
- ->from('products');
- $stmt = $select->query();
- $result = $stmt->fetchAll();
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.execute.tostring">
- <title>Преобразование объекта Select в SQL-строку</title>
- <para>
- Если нужно получить доступ к строковому представлению
- SQL-запроса, соответствующего данному объекту Zend_Db_Select, то
- используйте метод <code>__toString()</code>.
- </para>
- <example id="zend.db.select.execute.tostring.example">
- <title>Пример использования метода __toString()</title>
- <programlisting language="php"><![CDATA[
- $select = $db->select()
- ->from('products');
- $sql = $select->__toString();
- echo "$sql\n";
- // Выводится будет строка:
- // SELECT * FROM "products"
- ]]>
- </programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.select.other">
- <title>Другие методы</title>
- <para>
- Этот раздел описывает другие методы класса Zend_Db_Select, которые
- не были охвачены ранее: <code>getPart()</code> и
- <code>reset()</code>.
- </para>
- <sect3 id="zend.db.select.other.get-part">
- <title>Получение частей объекта Select</title>
- <para>
- Метод <code>getPart()</code> возвращает представление
- определенной части вашего запроса. Например, вы можете
- использовать этот метод для получения строки выражения для
- предложения <code>WHERE</code>, массива столбцов, перечисленных
- для получения выборки по ним, значений количества и смещения для
- предложения <code>LIMIT</code>.
- </para>
- <para>
- Возвращаемое значение не является строкой, содержащей фрагмент
- запроса SQL. Возвращаемое значение является внутренним
- представлением в объекте, обычно это массив, содержащий значения
- и выражения. Каждая часть запроса имеет различную структуру.
- </para>
- <para>
- Единственным аргументом метода <code>getPart()</code> является
- строка, идентифицирующая часть запроса, которую требуется
- вернуть. Например, строка <code>'from'</code> соответствует той
- части запроса, которая хранит информацию о таблицах в
- предложении <code>FROM</code>, включая присоединяемые таблицы.
- </para>
- <para>
- Zend_Db_Select определяет константы, которые вы можете
- использовать для частей SQL-запроса. Вы можете использовать эти
- константы или литеральные строки.
- </para>
- <table id="zend.db.select.other.get-part.table">
- <title>Константы, используемые методами getPart() и reset()</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Константа</entry>
- <entry>Строковое значение</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><code>Zend_Db_Select::DISTINCT</code></entry>
- <entry><code>'distinct'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::FOR_UPDATE</code></entry>
- <entry><code>'forupdate'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::COLUMNS</code></entry>
- <entry><code>'columns'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::FROM</code></entry>
- <entry><code>'from'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::WHERE</code></entry>
- <entry><code>'where'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::GROUP</code></entry>
- <entry><code>'group'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::HAVING</code></entry>
- <entry><code>'having'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::ORDER</code></entry>
- <entry><code>'order'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::LIMIT_COUNT</code></entry>
- <entry><code>'limitcount'</code></entry>
- </row>
- <row>
- <entry><code>Zend_Db_Select::LIMIT_OFFSET</code></entry>
- <entry><code>'limitoffset'</code></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <example id="zend.db.select.other.get-part.example">
- <title>Пример использования метода getPart()</title>
- <programlisting language="php"><![CDATA[
- $select = $db->select()
- ->from('products')
- ->order('product_id');
- // Вы можете использовать строковой литерал для указания части запроса
- $orderData = $select->getPart( 'order' );
- // Можно использовать константу для указания той же части
- $orderData = $select->getPart( Zend_Db_Select::ORDER );
- // Возвращаемое значение может быть массивом, а не строкой
- // Каждая часть имет свою структуру
- print_r( $orderData );
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.select.other.reset">
- <title>Сброс частей запроса в объекте Select</title>
- <para>
- Через метод <code>reset()</code> вы можете очистить
- определенную часть SQL-запроса или все части запроса, если
- опустить аргумент.
- </para>
- <para>
- Единственный аргумент метода является опциональным. Вы можете
- указать часть запроса для очистки, используя те же строки,
- которые используются для метода <code>getPart()</code>. Та часть
- запроса, которую вы указали, сбрасывается в состояние по
- умолчанию.
- </para>
- <para>
- Если вы опустите этот параметр, то <code>reset()</code>
- сбрасывает все части запроса в состояние по умолчанию. Это
- делает объект Zend_Db_Select эквивалентным новому объекту - так
- же, как если бы вы его только что инстанцировали его.
- </para>
- <example id="zend.db.select.other.reset.example">
- <title>Пример использования метода reset()</title>
- <programlisting language="php"><![CDATA[
- // Строит запрос:
- // SELECT p.*
- // FROM "products" AS p
- // ORDER BY "product_name"
- $select = $db->select()
- ->from(array('p' => 'products')
- ->order('product_name');
- // Changed requirement, instead order by a different columns:
- // Теперь нужна сортировка по другому столбцу:
- // SELECT p.*
- // FROM "products" AS p
- // ORDER BY "product_id"
- // Очищаем соответствующую часть, теперь можно переопределить ее
- $select->reset( Zend_Db_Select::ORDER );
- // Задаем другой столбец
- $select->order('product_id');
- // Очищаем все части запроса
- $select->reset();
- ]]>
- </programlisting>
- </example>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|