mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-04 15:24:07 +01:00
913 lines
40 KiB
Plaintext
913 lines
40 KiB
Plaintext
Построитель запросов
|
||
====================
|
||
|
||
Построитель запросов Yii предоставляет объектно-ориентированный способ
|
||
написания SQL-запросов. Он позволяет разработчику использовать методы и свойства
|
||
класса для того, чтобы указать отдельные части SQL запроса. За тем, построитель
|
||
собирает отдельные части в SQL запрос, который может быть затем выполнен вызовом
|
||
методов DAO, как описано в «[Объекты доступа к данным (DAO)](/doc/guide/database.dao)».
|
||
Сдедующий код показывает типичное использование построителя запросов для получения
|
||
SQL-запроса SELECT:
|
||
|
||
~~~
|
||
[php]
|
||
$user = Yii::app()->db->createCommand()
|
||
->select('id, username, profile')
|
||
->from('tbl_user u')
|
||
->join('tbl_profile p', 'u.id=p.user_id')
|
||
->where('id=:id', array(':id'=>$id))
|
||
->queryRow();
|
||
~~~
|
||
|
||
|
||
Построитель запросов лучше всего использовать в том случае, когда необходимо
|
||
собрать SQL запрос следуя некоторой условной логике приложения. Основными достоинствами
|
||
построителя запросов является то, что он:
|
||
|
||
* Позволяет собрать сложный SQL-запрос програмно.
|
||
|
||
* Автоматически экранирует имена таблиц и полей, чтобы не допустить конфликта
|
||
с ключевыми словами SQL и специальными символами.
|
||
|
||
* Экранирует значения параметров и, где это возможно, использует привязку
|
||
параметров, что помогает избежать SQL-инъекций.
|
||
|
||
* Предоставляет слой абстракции, который упрощает переход на другие СУБД.
|
||
|
||
|
||
Использовать построитель запросов не обязательно. Если ваши запросы простые, легче
|
||
и быстрее использовать именно SQL.
|
||
|
||
|
||
Подготовка построителя запросов
|
||
-------------------------------
|
||
|
||
Построитель запросов реализован в классе [CDbCommand] — главном классе для
|
||
работы с базой данных, описанном в «[Объекты доступа к данным (DAO)](/doc/guide/database.dao)».
|
||
|
||
Для того, чтобы начать его использовать необходимо создать новый экземпляр
|
||
[CDbCommand]:
|
||
|
||
~~~
|
||
[php]
|
||
$command = Yii::app()->db->createCommand();
|
||
~~~
|
||
|
||
Здесь мы используем `Yii::app()->db` для получения соединения с базой данных и,
|
||
затем, вызываем [CDbConnection::createCommand()] для создания экземпляра команды.
|
||
|
||
Стоит отметить, что вместо передачи `createCommand()` целого SQL, как это делалось
|
||
[в случае с DAO](/doc/guide/database.dao), мы не указываем параметр так как
|
||
мы соберём отдельные части запроса при помощи методов построителя, которые описаны
|
||
далее.
|
||
|
||
|
||
Запросы получения данных
|
||
------------------------
|
||
|
||
Запросы на получения данных соответствуют в SQL запросам SELECT. В построителе
|
||
есть ряд методов для сборки отдельных частей SELECT запроса. Так как все
|
||
эти методы возвращают экземпляр [CDbCommand], то мы можем использовать их
|
||
цепочкой, как показано в примере в начале этого раздела.
|
||
|
||
* [select|CDbCommand::select]: часть запроса после SELECT.
|
||
* [selectDistinct|CDbCommand::selectDistinct]: часть запроса после SELECT. Добавляет DISTINCT.
|
||
* [from|CDbCommand::from]: часть запроса после FROM.
|
||
* [where|CDbCommand::where]: часть запроса после WHERE.
|
||
* [join|CDbCommand::join]: добавляет к запросу INNER JOIN.
|
||
* [leftJoin|CDbCommand::leftJoin]: добавляет к запросу LEFT OUTER JOIN.
|
||
* [rightJoin|CDbCommand::rightJoin]: добавляет к запросу RIGHT OUTER JOIN.
|
||
* [crossJoin|CDbCommand::crossJoin]: добавляет к запросу CROSS JOIN.
|
||
* [naturalJoin|CDbCommand::naturalJoin]: добавляет к запросу NATURAL JOIN.
|
||
* [group|CDbCommand::group]: часть запроса после GROUP BY.
|
||
* [having|CDbCommand::having]: часть запроса после HAVING.
|
||
* [order|CDbCommand::order]: часть запроса после ORDER BY.
|
||
* [limit|CDbCommand::limit]: часть запроса после LIMIT.
|
||
* [offset|CDbCommand::offset]: часть запроса после OFFSET.
|
||
* [union|CDbCommand::union]: часть запроса после UNION.
|
||
|
||
|
||
Рассмотрим использование перечисленных методов. Для простоты предположим, что
|
||
запросы делаются к MySQL. Для других СУБД экранирование таблиц, полей и значений,
|
||
показанное в примерах, может отличаться.
|
||
|
||
|
||
### select
|
||
|
||
~~~
|
||
[php]
|
||
function select($columns='*')
|
||
~~~
|
||
|
||
Метод [select|CDbCommand::select] задаёт часть запроса после `SELECT`. Параметр
|
||
`$columns` определяет выбираемы поля и может быть либо списком имён выбираемых
|
||
полей, разделённых запятой, либо массивом имён полей. Имена могут содержать
|
||
префиксы таблиц и псевдонимы полей. Метод автоматически экранирует имена, если
|
||
в имени поля нет скобок (что означает использование выражения).
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// SELECT *
|
||
select()
|
||
// SELECT `id`, `username`
|
||
select('id, username')
|
||
// SELECT `tbl_user`.`id`, `username` AS `name`
|
||
select('tbl_user.id, username as name')
|
||
// SELECT `id`, `username`
|
||
select(array('id', 'username'))
|
||
// SELECT `id`, count(*) as num
|
||
select(array('id', 'count(*) as num'))
|
||
~~~
|
||
|
||
|
||
### selectDistinct
|
||
|
||
~~~
|
||
[php]
|
||
function selectDistinct($columns)
|
||
~~~
|
||
|
||
Метод [selectDistinct|CDbCommand::selectDistinct] делает то же, что и метод
|
||
[select|CDbCommand::select] плюс добавляет к выражению `DISTINCT`. К примеру,
|
||
`selectDistinct('id, username')` сгенеруреут следующий SQL:
|
||
|
||
~~~
|
||
SELECT DISTINCT `id`, `username`
|
||
~~~
|
||
|
||
|
||
### from
|
||
|
||
~~~
|
||
[php]
|
||
function from($tables)
|
||
~~~
|
||
|
||
Метод [from|CDbCommand::from] задаёт часть запроса после `FROM`. Параметр
|
||
`$tables` определяет, из каких таблиц производится выборка и может быть либо
|
||
списком имён таблиц, разделённым запятыми, либо массивом имён таблиц. Имена могут
|
||
содержать префиксы схемы (такие, как `public.tbl_user`) и псевдонимы таблиц
|
||
(такие, как `tbl_user u`). Метод автоматически экранирует имена, если в них нет
|
||
скобок (что означает использование подзапроса или выражения).
|
||
|
||
Примеры:
|
||
|
||
~~~
|
||
[php]
|
||
// FROM `tbl_user`
|
||
from('tbl_user')
|
||
// FROM `tbl_user` `u`, `public`.`tbl_profile` `p`
|
||
from('tbl_user u, public.tbl_profile p')
|
||
// FROM `tbl_user`, `tbl_profile`
|
||
from(array('tbl_user', 'tbl_profile'))
|
||
// FROM `tbl_user`, (select * from tbl_profile) p
|
||
from(array('tbl_user', '(select * from tbl_profile) p'))
|
||
~~~
|
||
|
||
|
||
### where
|
||
|
||
~~~
|
||
[php]
|
||
function where($conditions, $params=array())
|
||
~~~
|
||
|
||
Метод [where|CDbCommand::where] задаёт часть запроса после `WHERE`. Параметр
|
||
`$conditions` определяет условия запроса, а `$params` — параметры, которые
|
||
подставляются в запрос. Значение параметра `$conditions` может быть как строкой
|
||
(например, `id=1`) так и массивом следующего вида:
|
||
|
||
~~~
|
||
[php]
|
||
array(operator, operand1, operand2, ...)
|
||
~~~
|
||
|
||
где `operator` может быть одинм из следующего:
|
||
|
||
* `and`: операнды соединяются при помощи `AND`. К примеру, `array('and', 'id=1', 'id=2')`
|
||
сгенеруреут `id=1 AND id=2`. Если операнд задан массивом, то он будет конвертирован
|
||
в строку с использованием описанных здесь правил. К примеру,
|
||
`array('and', 'type=1', array('or', 'id=1', 'id=2'))` сгенеруреут
|
||
`type=1 AND (id=1 OR id=2)`. Данный метод ничего НЕ экранирует.
|
||
|
||
* `or`: то же, что и `and` но для OR.
|
||
|
||
* `in`: первый операнд должнен быть столбцом или выражением, второй — массивом,
|
||
содержащим список значений, в которые должно входить значение поля или выражения.
|
||
К примеру, `array('in', 'id', array(1,2,3))` сгенеруреут `id IN (1,2,3)`.
|
||
Метод экранирует имя столбца и значения в списке.
|
||
|
||
* `not in`: то же, что и `in`, но вместо `IN` используется `NOT IN`.
|
||
|
||
* `like`: первый операнд должен быть именем поля или выражением, второй — строкой
|
||
или массивом, содержащим список значений, на которые должно быть похоже значение
|
||
поля или выражения. К примеру, `array('like', 'name', 'tester')` сгенеруреут
|
||
`name LIKE '%tester%'`. Когда список указывается массивом, генерируется несколько
|
||
`LIKE`, соединённых при помощи `AND`. К примеру,
|
||
`array('like', 'name', array('test', 'sample'))` сгенеруреут
|
||
`name LIKE '%test%' AND name LIKE '%sample%'`. Метод экранирует имена полей и
|
||
значения в списке.
|
||
|
||
* `not like`: то же, что и `like`, но вместо `LIKE` генерируется `NOT LIKE`.
|
||
|
||
* `or like`: то же, что и `like` но для соединения `LIKE` используется `OR`.
|
||
|
||
* `or not like`: то же, что и `not like` но для соединения `NOT LIKE` используется `OR`.
|
||
|
||
|
||
Несколько примеров использования `where`:
|
||
|
||
~~~
|
||
[php]
|
||
// WHERE id=1 or id=2
|
||
where('id=1 or id=2')
|
||
// WHERE id=:id1 or id=:id2
|
||
where('id=:id1 or id=:id2', array(':id1'=>1, ':id2'=>2))
|
||
// WHERE id=1 OR id=2
|
||
where(array('or', 'id=1', 'id=2'))
|
||
// WHERE id=1 AND (type=2 OR type=3)
|
||
where(array('and', 'id=1', array('or', 'type=2', 'type=3')))
|
||
// WHERE `id` IN (1, 2)
|
||
where(array('in', 'id', array(1, 2))
|
||
// WHERE `id` NOT IN (1, 2)
|
||
where(array('not in', 'id', array(1,2)))
|
||
// WHERE `name` LIKE '%Qiang%'
|
||
where(array('like', 'name', '%Qiang%'))
|
||
// WHERE `name` LIKE '%Qiang' AND `name` LIKE '%Xue'
|
||
where(array('like', 'name', array('%Qiang', '%Xue')))
|
||
// WHERE `name` LIKE '%Qiang' OR `name` LIKE '%Xue'
|
||
where(array('or like', 'name', array('%Qiang', '%Xue')))
|
||
// WHERE `name` NOT LIKE '%Qiang%'
|
||
where(array('not like', 'name', '%Qiang%'))
|
||
// WHERE `name` NOT LIKE '%Qiang%' OR `name` NOT LIKE '%Xue%'
|
||
where(array('or not like', 'name', array('%Qiang%', '%Xue%')))
|
||
~~~
|
||
|
||
Стоит отметить, что в случае, когда оператор содержит `like`, необходимо явно
|
||
задавать спецсимволы (вроде `%` и `_`). Если паттерн вводится пользователем, то
|
||
необходимо использовать приведённый ниже код для экранирования спецсимволов и
|
||
предотвращения интерпретации их как спецсимволов:
|
||
|
||
~~~
|
||
[php]
|
||
$keyword=$_GET['q'];
|
||
// экранирует символы % и _
|
||
$keyword=strtr($keyword, array('%'=>'\%', '_'=>'\_'));
|
||
$command->where(array('like', 'title', '%'.$keyword.'%'));
|
||
~~~
|
||
|
||
### order
|
||
|
||
~~~
|
||
[php]
|
||
function order($columns)
|
||
~~~
|
||
|
||
Метод [order|CDbCommand::order] задаёт часть запроса после `ORDER BY`. Параметр
|
||
`$columns` определяет, по каким полям будет производится сортировка. Поля могут
|
||
быть указаны как в виде строки, содержащей список полей и направлений
|
||
(`ASC` или `DESC`), разделённых запятыми, так и массив полей и направлений.
|
||
Имена полей могут содержать префиксы таблиц. Метод автоматически экранирует
|
||
имена полей, если они не содержат скобок (что означает использование выражения).
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// ORDER BY `name`, `id` DESC
|
||
order('name, id desc')
|
||
// ORDER BY `tbl_profile`.`name`, `id` DESC
|
||
order(array('tbl_profile.name', 'id desc')
|
||
~~~
|
||
|
||
|
||
### limit и offset
|
||
|
||
~~~
|
||
[php]
|
||
function limit($limit, $offset=null)
|
||
function offset($offset)
|
||
~~~
|
||
|
||
Методы [limit|CDbCommand::limit] и [offset|CDbCommand::offset] задают
|
||
части запроса, идущие после `LIMIT` и `OFFSET`. Стоит отметить, что не все
|
||
СУБД поддерживают именно синтаксис `LIMIT` и `OFFSET`. Если он не поддерживается,
|
||
то построитель запросов переписывает весь SQL запрос для достижения схожего
|
||
эффекта.
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// LIMIT 10
|
||
limit(10)
|
||
// LIMIT 10 OFFSET 20
|
||
limit(10, 20)
|
||
// OFFSET 20
|
||
offset(20)
|
||
~~~
|
||
|
||
|
||
### join и его варианты
|
||
|
||
~~~
|
||
[php]
|
||
function join($table, $conditions, $params=array())
|
||
function leftJoin($table, $conditions, $params=array())
|
||
function rightJoin($table, $conditions, $params=array())
|
||
function crossJoin($table)
|
||
function naturalJoin($table)
|
||
~~~
|
||
|
||
Метод [join|CDbCommand::join] и его варианты задают порядок и параметры
|
||
объединения таблиц с использованием `INNER JOIN`, `LEFT OUTER JOIN`,
|
||
`RIGHT OUTER JOIN`, `CROSS JOIN` и `NATURAL JOIN`. Параметр `$table` определяет
|
||
таблицу, с которой производится объединение. Имя таблицы может содержать
|
||
префикс схемы или псевдоним. Метод экранирует имя таблицы, если оно не
|
||
содержит скобок, что означает использование подзапроса или выражения. Параметр
|
||
`$conditions` задаёт условие объединения. Синтаксис такой же, как и у
|
||
[where|CDbCommand::where]. Через `$params` указываются параметры, подставляемые
|
||
в запрос.
|
||
|
||
Стоит отметить, что этот метод отличается от остальных тем, что каждый следующие его
|
||
вызов добавляет часть запроса к предыдущим.
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// JOIN `tbl_profile` ON user_id=id
|
||
join('tbl_profile', 'user_id=id')
|
||
// LEFT JOIN `pub`.`tbl_profile` `p` ON p.user_id=id AND type=:type
|
||
leftJoin('pub.tbl_profile p', 'p.user_id=id AND type=:type', array(':type'=>1))
|
||
~~~
|
||
|
||
|
||
### group
|
||
|
||
~~~
|
||
[php]
|
||
function group($columns)
|
||
~~~
|
||
|
||
Метод [group|CDbCommand::group] задаёт часть запроса после `GROUP BY`.
|
||
Параметр `$columns` определяет поля, по которым будет осуществляться группировка
|
||
и может быть либо строкой разделённых запятыми полей, либо массивом полей.
|
||
Имена полей могут содержать префиксы. Метод автоматически экранирует имена полей
|
||
если они не содержат скобок (что означает использование выражений).
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// GROUP BY `name`, `id`
|
||
group('name, id')
|
||
// GROUP BY `tbl_profile`.`name`, `id`
|
||
group(array('tbl_profile.name', 'id')
|
||
~~~
|
||
|
||
|
||
### having
|
||
|
||
~~~
|
||
[php]
|
||
function having($conditions, $params=array())
|
||
~~~
|
||
|
||
Метод [having|CDbCommand::having] задаёт часть запроса после `HAVING`. Используется
|
||
точно так же, как и [where|CDbCommand::where].
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// HAVING id=1 or id=2
|
||
having('id=1 or id=2')
|
||
// HAVING id=1 OR id=2
|
||
having(array('or', 'id=1', 'id=2'))
|
||
~~~
|
||
|
||
|
||
### union
|
||
|
||
~~~
|
||
[php]
|
||
function union($sql)
|
||
~~~
|
||
|
||
Метод [union|CDbCommand::union] задаёт часть запроса после `UNION`. Он добавляет
|
||
`$sql` к сгенерированному запросу используя `UNION`. Несколько вызовов `union()`
|
||
добавят несколько чатей запроса.
|
||
|
||
Несколько примеров:
|
||
|
||
~~~
|
||
[php]
|
||
// UNION (select * from tbl_profile)
|
||
union('select * from tbl_profile')
|
||
~~~
|
||
|
||
|
||
### Выполнение запросов
|
||
|
||
После вызова методов для построения запроса, приведённых ниже, для выполнения
|
||
запроса можно использовать методы DAO, как описано в разделе
|
||
«[Объекты доступа к данным (DAO)](/doc/guide/database.dao)». К примеру, мы можем
|
||
вызвать [CDbCommand::queryRow()] для получения строки или [CDbCommand::queryAll()]
|
||
для получения всех строк сразу.
|
||
|
||
Пример:
|
||
|
||
~~~
|
||
[php]
|
||
$users = Yii::app()->db->createCommand()
|
||
->select('*')
|
||
->from('tbl_user')
|
||
->queryAll();
|
||
~~~
|
||
|
||
|
||
### Получение SQL
|
||
|
||
Кроме выполнения запросов, которые мы создали при помощи построителя, можно
|
||
также получить их SQL. Сделать это можно при помощи [CDbCommand::getText()].
|
||
|
||
~~~
|
||
[php]
|
||
$sql = Yii::app()->db->createCommand()
|
||
->select('*')
|
||
->from('tbl_user')
|
||
->text;
|
||
~~~
|
||
|
||
Если у запроса есть параметры, получить их можно при помощи свойства
|
||
[CDbCommand::params].
|
||
|
||
|
||
### Альтернативный синтаксис построения запросов
|
||
|
||
Иногда использование цепочек вызовов может быть неоптимальным решением. Построитель
|
||
запросов Yii позволяет создать запрос путём задания полей объекта. Для каждого
|
||
метода построителя запросов есть соответствующее поле с таким же именем.
|
||
Присвоение значения полю эквивалентно вызову соответствующего метода. К примеру,
|
||
приведённые ниже строки эквивалентны, если `$command` — объект [CDbCommand]:
|
||
|
||
~~~
|
||
[php]
|
||
$command->select(array('id', 'username'));
|
||
$command->select = array('id', 'username');
|
||
~~~
|
||
|
||
Более того, метод [CDbConnection::createCommand()] может принимать массив в
|
||
качестве параметра. Пары имя-значение из массива будут использованы для инициализации
|
||
полей созданного экземпляра [CDbCommand]. То есть для построения запроса можно
|
||
использовать следующий код:
|
||
|
||
~~~
|
||
[php]
|
||
$row = Yii::app()->db->createCommand(array(
|
||
'select' => array('id', 'username'),
|
||
'from' => 'tbl_user',
|
||
'where' => 'id=:id',
|
||
'params' => array(':id'=>1),
|
||
))->queryRow();
|
||
~~~
|
||
|
||
|
||
### Построение нескольких запросов
|
||
|
||
Для построения нескольких запросов экземпляр [CDbCommand] может быть
|
||
использован несколько раз. Перед тем, как построить новый запрос необходимо
|
||
вызвать метод [CDbCommand::reset()] для очистки предыдушего запроса. Пример:
|
||
|
||
~~~
|
||
[php]
|
||
$command = Yii::app()->createCommand();
|
||
$users = $command->select('*')->from('tbl_users')->queryAll();
|
||
$command->reset(); // clean up the previous query
|
||
$posts = $command->select('*')->from('tbl_posts')->queryAll();
|
||
~~~
|
||
|
||
|
||
Построение запросов для изменения данных
|
||
----------------------------------------
|
||
|
||
К запросам для изменения данных отностятся SQL запросы для вставки, обновления и
|
||
удаления данных из базы. В построителе запросов есть соответствующие методы
|
||
`insert`, `update` и `delete`. В отличие от запросов получения данных, описанных
|
||
выше, данные методы строят полный SQL-запрос и тут же выполняют его.
|
||
|
||
* [insert|CDbCommand::insert]: вставляет строку в таблицу
|
||
* [update|CDbCommand::update]: обновляет данные в таблице
|
||
* [delete|CDbCommand::delete]: удаляет данные из таблицы
|
||
|
||
|
||
### insert
|
||
|
||
~~~
|
||
[php]
|
||
function insert($table, $columns)
|
||
~~~
|
||
|
||
Метод [insert|CDbCommand::insert] строит и выполняет SQL запрос `INSERT`. Параметр
|
||
`$table` указывает, в какую таблицу производится вставка, а `$columns` — задаёт
|
||
массив пар имя-значение поля для вставки. Метод экранирует имя таблицы и использует
|
||
параметры для вставляемых значений.
|
||
|
||
Пример:
|
||
|
||
~~~
|
||
[php]
|
||
// строим и выполняем следующий SQL:
|
||
// INSERT INTO `tbl_user` (`name`, `email`) VALUES (:name, :email)
|
||
$command->insert('tbl_user', array(
|
||
'name'=>'Tester',
|
||
'email'=>'tester@example.com',
|
||
));
|
||
~~~
|
||
|
||
|
||
### update
|
||
|
||
~~~
|
||
[php]
|
||
function update($table, $columns, $conditions='', $params=array())
|
||
~~~
|
||
|
||
Метод [update|CDbCommand::update] строит и выполняет SQL запрос `UPDATE`. Параметр
|
||
`$table` указывает обновляемую таблицу; `$columns` является массивом пар имя-значение,
|
||
задающим значения обновлямых полей; `$conditions` и `$params` эквивалентны таким же
|
||
параметрам в [where|CDbCommand::where] и определяют часть запроса `UPDATE` после
|
||
`WHERE`. Метод экранирует имя таблицы и использует параметры для обновляемых значений.
|
||
|
||
Пример:
|
||
|
||
~~~
|
||
[php]
|
||
// строим и выполняем следующий SQL:
|
||
// UPDATE `tbl_user` SET `name`=:name WHERE id=:id
|
||
$command->update('tbl_user', array(
|
||
'name'=>'Tester',
|
||
), 'id=:id', array(':id'=>1));
|
||
~~~
|
||
|
||
|
||
### delete
|
||
|
||
~~~
|
||
[php]
|
||
function delete($table, $conditions='', $params=array())
|
||
~~~
|
||
|
||
Метод [delete|CDbCommand::delete] строит и выполняет SQL запрос `DELETE`. Параметр
|
||
`$table` указывает таблицу, из которой удаляются значения; `$conditions` и `$params`
|
||
эквивалентны таким же параметрам в [where|CDbCommand::where], которые определяют
|
||
часть запроса `DELETE` после `WHERE`. Метод экранирует имя таблицы.
|
||
|
||
Пример:
|
||
|
||
~~~
|
||
[php]
|
||
// строим и выполняем следующий SQL:
|
||
// DELETE FROM `tbl_user` WHERE id=:id
|
||
$command->delete('tbl_user', 'id=:id', array(':id'=>1));
|
||
~~~
|
||
|
||
Построение запросов изменения схемы
|
||
-----------------------------------
|
||
|
||
Кроме обычных запросов для получения данных и работы с ними, построитель
|
||
может собирать и выполнять SQL-запросы для изменения схемы базы данных.
|
||
Поддерживаются следующие запросы:
|
||
|
||
* [createTable|CDbCommand::createTable]: создание таблицы
|
||
* [renameTable|CDbCommand::renameTable]: переименование таблицы
|
||
* [dropTable|CDbCommand::dropTable]: удаление таблицы
|
||
* [truncateTable|CDbCommand::truncateTable]: очистка таблицы
|
||
* [addColumn|CDbCommand::addColumn]: добавление нового поля в таблицу
|
||
* [renameColumn|CDbCommand::renameColumn]: переименование поля таблицы
|
||
* [alterColumn|CDbCommand::alterColumn]: изменение поля таблицы
|
||
* [dropColumn|CDbCommand::dropColumn]: удаление поля таблицы
|
||
* [createIndex|CDbCommand::createIndex]: создание индекса
|
||
* [dropIndex|CDbCommand::dropIndex]: удаление индекса
|
||
|
||
> Info|Информация: Несмотря на то, что для разных СУБД запросы для измения схемы
|
||
разные, построитель запросов предоставляет единый интерфейс для их создания.
|
||
Это упрощает задачу мигрирования с одной СУБД на другую.
|
||
|
||
|
||
### Абстрактные типы данных
|
||
|
||
Построитель запросов вводит ряд абстрактных типов данных, которые можно
|
||
использовать для описания полей таблицы. В отличие от реальных типов данных,
|
||
которые отличаются в разных СУБД, абстрактные типы не зависят от СУБД.
|
||
При использовании их для описания типов полей, построитель запросов конвертирует
|
||
абстрактные типы в соответствующие им реальные.
|
||
|
||
Построитель запросов поддерживает следующие абстрактные типы:
|
||
|
||
* `pk`: обычный первичный ключ. Для MySQL конвертируется в `int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`;
|
||
* `string`: строка. Для MySQL конвертируется в `varchar(255)`;
|
||
* `text`: текстовый тип (длинная строка). Для MySQL конвертируется в `text`;
|
||
* `integer`: целое. Для MySQL конвертируется в `int(11)`;
|
||
* `float`: число с плавающей точкой. Для MySQL конвертируется в `float`;
|
||
* `decimal`: дясятичное число. Для MySQL конвертируется в `decimal`;
|
||
* `datetime`: дата и время. Для MySQL конвертируется в `datetime`;
|
||
* `timestamp`: метка времени. Для MySQL конвертируется в `timestamp`;
|
||
* `time`: время. Для MySQL конвертируется в `time`;
|
||
* `date`: дата. Для MySQL конвертируется в `date`;
|
||
* `binary`: бинарный. Для MySQL конвертируется в `blob`;
|
||
* `boolean`: булевый. Для MySQL конвертируется в `tinyint(1)`.
|
||
|
||
|
||
###createTable
|
||
|
||
~~~
|
||
[php]
|
||
function createTable($table, $columns, $options=null)
|
||
~~~
|
||
|
||
Метод [createTable|CDbCommand::createTable] строит и выполняет SQL запрос для
|
||
создания таблицы. Параметр `$table` задаёт имя создаваемой таблицы. Параметр
|
||
`$columns` определяет поля новой таблицы. Они должны быть указаны в виде пар
|
||
имя-определение (т.е. `'username'=>'string'`). Параметр `$options` задаёт
|
||
дополнительный фрагмент SQL, который будет добавлен к генерируемому SQL.
|
||
Построитель запроса экранирует имя таблицы и имена полей.
|
||
|
||
Для указания определения поля можно использовать абстрактный тип данных, как уже
|
||
было описано ранее. Построитель конвертирует абстрактный тип дынных в
|
||
соответствующий реальный тип данных в соответствии с используемой СУБД. К примеру,
|
||
`string` в случае MySQL сконвертируется в `varchar(255)`.
|
||
|
||
Определение поля также может содержать неабстрактный тип данных и спецификаций.
|
||
Они будут в результирующем SQL без каких-либо изменений. К примеру,
|
||
`point` не является абстрактным типом данных и при использовании в определении
|
||
поля будет включён в получающийся SQL как есть. `string NOT NULL` будет
|
||
конвертирован в `varchar(255) NOT NULL` (т.е. конвертируются только абстрактнй
|
||
тип `string`).
|
||
|
||
Пример создания таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// CREATE TABLE `tbl_user` (
|
||
// `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
// `username` varchar(255) NOT NULL,
|
||
// `location` point
|
||
// ) ENGINE=InnoDB
|
||
createTable('tbl_user', array(
|
||
'id' => 'pk',
|
||
'username' => 'string NOT NULL',
|
||
'location' => 'point',
|
||
), 'ENGINE=InnoDB')
|
||
~~~
|
||
|
||
|
||
###renameTable
|
||
|
||
~~~
|
||
[php]
|
||
function renameTable($table, $newName)
|
||
~~~
|
||
|
||
Метод [renameTable|CDbCommand::renameTable] строит и выполняет SQL запрос для
|
||
пепеименования таблицы. Параметр `$table` задаёт имя переименовываемой таблицы.
|
||
Параметр `$newName` определяет новое имя таблицы. Построитель запроса
|
||
экранирует имена таблицы.
|
||
|
||
Пример переименования таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// RENAME TABLE `tbl_users` TO `tbl_user`
|
||
renameTable('tbl_users', 'tbl_user')
|
||
~~~
|
||
|
||
|
||
###dropTable
|
||
|
||
~~~
|
||
[php]
|
||
function dropTable($table)
|
||
~~~
|
||
|
||
Метод [dropTable|CDbCommand::dropTable] строит и выполняет SQL запрос для удаления
|
||
таблицы. Параметр `$table` определяет имя удаляемой таблицы. Построитель запроса
|
||
экранирует имя таблицы.
|
||
|
||
Пример удаления теблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// DROP TABLE `tbl_user`
|
||
dropTable('tbl_user')
|
||
~~~
|
||
|
||
###truncateTable
|
||
|
||
~~~
|
||
[php]
|
||
function truncateTable($table)
|
||
~~~
|
||
|
||
Метод [truncateTable|CDbCommand::truncateTable] строит и выполняет SQL запрос для
|
||
очистки всех данных таблицы. Параметр `$table` определяет имя очищаемой таблицы.
|
||
Построитель запроса экранирует имя таблицы.
|
||
|
||
Пример очистки таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// TRUNCATE TABLE `tbl_user`
|
||
truncateTable('tbl_user')
|
||
~~~
|
||
|
||
|
||
###addColumn
|
||
|
||
~~~
|
||
[php]
|
||
function addColumn($table, $column, $type)
|
||
~~~
|
||
|
||
Метод [addColumn|CDbCommand::addColumn] строит и выполняет SQL запрос для
|
||
добавления нового поля таблицы. Параметр `$table` задаёт имя таблицы, к которой
|
||
будет добавляться новое поле. Параметр `$column` — имя нового поля. `$type`
|
||
задаёт тип поля. Определение поля может содержать абстрактный тип данных,
|
||
как уже было описано в подразделе «createTable». Построитель запроса
|
||
экранирует имя таблицы и имя поля.
|
||
|
||
Пример добавления поля:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_user` ADD `email` varchar(255) NOT NULL
|
||
addColumn('tbl_user', 'email', 'string NOT NULL')
|
||
~~~
|
||
|
||
|
||
###dropColumn
|
||
|
||
~~~
|
||
[php]
|
||
function dropColumn($table, $column)
|
||
~~~
|
||
|
||
Метод [dropColumn|CDbCommand::dropColumn] строит и выполняет SQL запрос для
|
||
удаления поля таблицы. Параметр `$table` задаёт имя таблицы из которой удаляется
|
||
поле. Параметр `$column` определяет имя удаляемого поля. Построитель запроса
|
||
экранирует имя таблицы и имя поля.
|
||
|
||
Пример удаления поля таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_user` DROP COLUMN `location`
|
||
dropColumn('tbl_user', 'location')
|
||
~~~
|
||
|
||
|
||
###renameColumn
|
||
|
||
~~~
|
||
[php]
|
||
function renameColumn($table, $name, $newName)
|
||
~~~
|
||
|
||
Метод [renameColumn|CDbCommand::renameColumn] строит и выполняет SQL запрос для
|
||
переименования поля таблицы. Параметр `$table` задаёт имя таблицы, поле которой
|
||
будет переименовано. Параметр `$name` определяет имя переимновываемого поля.
|
||
`$newName` задаёт имя нового поля. Построитель запроса экранирует имя таблицы и
|
||
имена полей.
|
||
|
||
Пример переименования поля таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_users` CHANGE `name` `username` varchar(255) NOT NULL
|
||
renameColumn('tbl_user', 'name', 'username')
|
||
~~~
|
||
|
||
|
||
###alterColumn
|
||
|
||
~~~
|
||
[php]
|
||
function alterColumn($table, $column, $type)
|
||
~~~
|
||
|
||
Метод [alterColumn|CDbCommand::alterColumn] строит и выполняет SQL запрос для
|
||
изменения поля таблицы. Параметр `$table` задаёт имя таблицы, поле которой
|
||
будет изменено. Параметр `$column` определяет имя изменяемого поля. `$type`
|
||
задаёт новое определение поля, которое может содержать абстрактный тип данных,
|
||
как было описано в подразделе «createTable». Построитель запросов экранирует имя
|
||
таблицы и имя поля.
|
||
|
||
Пример изменения поля таблицы:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_user` CHANGE `username` `username` varchar(255) NOT NULL
|
||
alterColumn('tbl_user', 'username', 'string NOT NULL')
|
||
~~~
|
||
|
||
|
||
|
||
|
||
###addForeignKey
|
||
|
||
~~~
|
||
[php]
|
||
function addForeignKey($name, $table, $columns,
|
||
$refTable, $refColumns, $delete=null, $update=null)
|
||
~~~
|
||
|
||
Метод [addForeignKey|CDbCommand::addForeignKey] строит и выполняет SQL запрос для
|
||
добавления внешнего ключа в таблицу. Параметр `$name` задаёт имя внешнего ключа.
|
||
Параметры `$table` и `$columns` определяют имя таблицы и имя поля внешнего
|
||
ключа. Если указаны несколько полей, то они должны быть разделены запятыми.
|
||
Параметры `$refTable` и `$refColumns` определяют имя таблицы и имя поля, на которое
|
||
ссылается внешний ключ. Параметры `$delete` и `$update` задают SQL-опции
|
||
`ON DELETE` и `ON UPDATE` соответственно. Большинство СУБД поддерживают
|
||
следующие опции: `RESTRICT`, `CASCADE`, `NO ACTION`, `SET DEFAULT` и `SET NULL`.
|
||
Построитель запросов экранирует имя таблицы, имя индекса и имена полей.
|
||
|
||
Пример добавления внешнего ключа:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_profile` ADD CONSTRAINT `fk_profile_user_id`
|
||
// FOREIGN KEY (`user_id`) REFERENCES `tbl_user` (`id`)
|
||
// ON DELETE CASCADE ON UPDATE CASCADE
|
||
addForeignKey('fk_profile_user_id', 'tbl_profile', 'user_id',
|
||
'tbl_user', 'id', 'CASCADE', 'CASCADE')
|
||
~~~
|
||
|
||
|
||
###dropForeignKey
|
||
|
||
~~~
|
||
[php]
|
||
function dropForeignKey($name, $table)
|
||
~~~
|
||
|
||
Метод [dropForeignKey|CDbCommand::dropForeignKey] строит и выполняет SQL запрос
|
||
для удаления внешнего ключа. Параметр `$name` задаёт имя внешнего ключа,
|
||
который требуется удалить. Параметр `$table` — имя таблицы, из которой
|
||
удаляется ключ. Построитель запроса экранирует имя таблицы и имя ключа.
|
||
|
||
Пример удаления внешнего ключа:
|
||
|
||
~~~
|
||
[php]
|
||
// ALTER TABLE `tbl_profile` DROP FOREIGN KEY `fk_profile_user_id`
|
||
dropForeignKey('fk_profile_user_id', 'tbl_profile')
|
||
~~~
|
||
|
||
|
||
###createIndex
|
||
|
||
~~~
|
||
[php]
|
||
function createIndex($name, $table, $column, $unique=false)
|
||
~~~
|
||
|
||
Метод [createIndex|CDbCommand::createIndex] строит и выполняет SQL запрос
|
||
для создания индекса. Параметр `$name` задаёт имя индекса, который будет создан.
|
||
Параметр `$table` — имя таблицы, в которой создаётся индекс. Параметр `$column`
|
||
— имя индексируемого поля. Параметр `$unique` определяет, должен ли быть
|
||
индекс уникальным. Если индекс состоит из нескольких полей, то они разделяются
|
||
запятыми. Построитель запросов экранирует имя таблицы, имя индекса и имена полей.
|
||
|
||
Пример создания индекса:
|
||
|
||
~~~
|
||
[php]
|
||
// CREATE INDEX `idx_username` ON `tbl_user` (`username`)
|
||
createIndex('idx_username', 'tbl_user')
|
||
~~~
|
||
|
||
|
||
###dropIndex
|
||
|
||
~~~
|
||
[php]
|
||
function dropIndex($name, $table)
|
||
~~~
|
||
|
||
Метод [dropIndex|CDbCommand::dropIndex] строит и выполняет SQL запрос для
|
||
удаления индекса. Параметр `$name` задаёт имя удаляемого индекса.
|
||
Параметр `$table` — имя таблицы, в которой создаётся индекс. Построитель
|
||
запроса экранирует имя таблицы и имя индекса.
|
||
|
||
Пример удаления индекса:
|
||
|
||
~~~
|
||
[php]
|
||
// DROP INDEX `idx_username` ON `tbl_user`
|
||
dropIndex('idx_username', 'tbl_user')
|
||
~~~
|
||
|
||
<div class="revision">$Id: database.query-builder.txt 2868 2011-01-15 22:11:10Z haertl.mike $</div> |