mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-13 11:37:15 +01:00
428 lines
16 KiB
Plaintext
428 lines
16 KiB
Plaintext
Query Builder
|
|
=============
|
|
|
|
The Yii Query Builder provides an object-orient way of writing SQL statements. It allows developers to use class methods and properties to specify individual parts of a SQL statement. It then assembles different parts into a valid SQL statement that can be further executed by calling the DAO methods as described in [Data Access Objects](/doc/guide/database.dao). The following shows a typical usage of the Query Builder:
|
|
|
|
~~~
|
|
[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();
|
|
~~~
|
|
|
|
|
|
The Query Builder is best used when you need to assemble a SQL statement procedurally, or based on some conditional logic in your application. The main benefits of using the Query Builder include:
|
|
|
|
* It allows building complex SQL statements programmatically.
|
|
|
|
* It automatically quotes table names and column names to prevent conflict with SQL reserved words and special characters.
|
|
|
|
* It also quotes parameter values and uses parameter binding when possible, which helps reduce risk of SQL injection attacks.
|
|
|
|
* It offers certain degree of DB abstraction, which simplifies migration to different DB platforms.
|
|
|
|
|
|
It is not mandatory to use the Query Builder. In fact, if your queries are simple, it is easier and faster to directly write SQL statements.
|
|
|
|
|
|
Preparing Query Builder
|
|
-----------------------
|
|
|
|
The Yii Query Builder is provided in terms of [CDbCommand], the main DB query class described in [Data Access Objects](/doc/guide/database.dao).
|
|
|
|
To start using the Query Builder, we create a new instance of [CDbCommand] as follows,
|
|
|
|
~~~
|
|
[php]
|
|
$command = Yii::app()->db->createCommand();
|
|
~~~
|
|
|
|
That is, we use `Yii::app()->db` to get the DB connection, and then call [CDbConnection::createCommand()] to create the needed command instance.
|
|
|
|
Note that instead of passing a whole SQL statement to the `createCommand()` call as we do in [Data Access Objects](/doc/guide/database.dao), we leave it empty. This is because we will build individual parts of the SQL statement using the Query Builder methods explained in the following.
|
|
|
|
|
|
Building Queries
|
|
----------------
|
|
|
|
Building a SQL query involves calling different query builder methods to build individual parts of the query. Because all these methods return the [CDbCommand] instance, we can call them using method chaining, as shown in the previous example.
|
|
|
|
In the following, we explain how to use these query builder methods. We assume the underlying database is MySQL. Note that if you are using other DBMS, the table/column/value quoting shown in the examples may be different.
|
|
|
|
|
|
### select
|
|
|
|
~~~
|
|
[php]
|
|
function select($columns='*')
|
|
~~~
|
|
|
|
The [select|CDbCommand::select] method specifies the `SELECT` part of a query. The `$columns` parameter specifies the columns to be selected, which can be either a string representing comma-separated columns, or an array of column names. Column names can contain table prefixes and/or column aliases. The method will automatically quote the column names unless a column contains some parenthesis (which means the column is given as a DB expression).
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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)
|
|
~~~
|
|
|
|
The [selectDistinct|CDbCommand::selectDistinct] method is similar as [select|CDbCommand::select] except that it turns on the `DISTINCT` flag. For example, `select('id, username')` will generate the following SQL:
|
|
|
|
~~~
|
|
SELECT DISTINCT `id`, `username`
|
|
~~~
|
|
|
|
|
|
### from
|
|
|
|
~~~
|
|
[php]
|
|
function from($tables)
|
|
~~~
|
|
|
|
The [from|CDbCommand::from] method specifies the `FROM` part of a query. The `$tables` parameter specifies which tables to be selected from. This can be either a string representing comma-separated table names, or an array of table names. Table names can contain schema prefixes (e.g. `public.tbl_user`) and/or table aliases (e.g. `tbl_user u`). The method will automatically quote the table names unless it contains some parenthesis (which means the table is given as a sub-query or DB expression).
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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())
|
|
~~~
|
|
|
|
The [where|CDbCommand::where] method specifies the `WHERE` part of a query. The `$conditions` parameter specifies query conditions while `$params` specifies the parameters to be bound to the whole query. The `$conditions` parameter can be either a string (e.g. `id=1`) or an array of the format:
|
|
|
|
~~~
|
|
[php]
|
|
array(operator, operand1, operand2, ...)
|
|
~~~
|
|
|
|
where `operator` can be any of the following:
|
|
|
|
* `and`: the operands should be concatenated together using `AND`. For example, `array('and', 'id=1', 'id=2')` will generate `id=1 AND id=2`. If an operand is an array, it will be converted into a string using the same rules described here. For example, `array('and', 'type=1', array('or', 'id=1', 'id=2'))` will generate `type=1 AND (id=1 OR id=2)`. The method will NOT do any quoting or escaping.
|
|
|
|
* `or`: similar as the `and` operator except that the operands are concatenated using OR.
|
|
|
|
* `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing the range of the values that the column or DB expression should be in. For example, `array('in', 'id', array(1,2,3))` will generate `id IN (1,2,3)`. The method will properly quote the column name and escape values in the range.
|
|
|
|
* `not in`: similar as the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
|
|
|
|
* `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing the range of the values that the column or DB expression should be like. For example, `array('like', 'name', 'tester')` will generate `name LIKE '%tester%'`. When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated using `AND`. For example, `array('like', 'name', array('test', 'sample'))` will generate `name LIKE '%test%' AND name LIKE '%sample%'`. The method will properly quote the column name and escape values in the range.
|
|
|
|
* `not like`: similar as the `like` operator except that `LIKE` is replaced with `NOT LIKE` in the generated condition.
|
|
|
|
* `or like`: similar as the `like` operator except that `OR` is used to concatenated several `LIKE` predicates.
|
|
|
|
* `or not like`: similar as the `not like` operator except that `OR` is used to concatenated several `NOT LIKE` predicates.
|
|
|
|
|
|
Below are some examples of using `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')))
|
|
~~~
|
|
|
|
|
|
### order
|
|
|
|
~~~
|
|
[php]
|
|
function order($columns)
|
|
~~~
|
|
|
|
The [order|CDbCommand::order] method specifies the `ORDER BY` part of a query.
|
|
The `$columns` parameter specifies the columns to be ordered by, which can be either a string representing comma-separated columns and order directions (`ASC` or `DESC`), or an array of columns and order directions. Column names can contain table prefixes. The method will automatically quote the column names unless a column contains some parenthesis (which means the column is given as a DB expression).
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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 and `offset`
|
|
|
|
~~~
|
|
[php]
|
|
function limit($limit, $offset=null)
|
|
function offset($offset)
|
|
~~~
|
|
|
|
The [limit|CDbCommand::limit] and [offset|CDbCommand::offset] methods specify the `LIMIT` and `OFFSET` part of a query. Note that some DBMS may not support `LIMIT` and `OFFSET` syntax. In this case, the Query Builder will rewrite the whole SQL statement to simulate the function of limit and offset.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
// LIMIT 10
|
|
limit(10)
|
|
// LIMIT 10 OFFSET 20
|
|
limit(10, 20)
|
|
// OFFSET 20
|
|
offset(20)
|
|
~~~
|
|
|
|
|
|
### join and its variants
|
|
|
|
~~~
|
|
[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)
|
|
~~~
|
|
|
|
The [join|CDbCommand::join] method and its variants specify how to join with other tables using `INNER JOIN`, `LEFT OUTER JOIN`, `RIGHT OUTER JOIN`, `CROSS JOIN`, or `NATURAL JOIN`. The `$table` parameter specifies which table to be joined with. The table name can contain schema prefix and/or alias. The method will quote the table name unless it contains a parenthesis meaning it is either a DB expression or sub-query. The `$conditions` parameter specifies the join condition. Its syntax is the same as that in [where|CDbCommand::where]. And `$params` specifies the parameters to be bound to the whole query.
|
|
|
|
Note that unlike other query builder methods, each call of a join method will be appended to the previous ones.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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)
|
|
~~~
|
|
|
|
The [group|CDbCommand::group] method specifies the `GROUP BY` part of a query.
|
|
The `$columns` parameter specifies the columns to be grouped by, which can be either a string representing comma-separated columns, or an array of columns. Column names can contain table prefixes. The method will automatically quote the column names unless a column contains some parenthesis (which means the column is given as a DB expression).
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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())
|
|
~~~
|
|
|
|
The [having|CDbCommand::having] method specifies the `HAVING` part of a query. Its usage is the same as [where|CDbCommand::where].
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[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)
|
|
~~~
|
|
|
|
The [union|CDbCommand::union] method specifies the `UNION` part of a query. It appends `$sql` to the existing SQL using `UNION` operator. Calling `union()` multiple times will append multiple SQLs to the existing SQL.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
// UNION (select * from tbl_profile)
|
|
union('select * from tbl_profile')
|
|
~~~
|
|
|
|
|
|
### insert
|
|
|
|
~~~
|
|
[php]
|
|
function insert($table, $columns)
|
|
~~~
|
|
|
|
The [insert|CDbCommand::insert] method specifies an `INSERT` SQL statement. The `$table` parameter specifies which table to be inserted into, while `$columns` is an array of name-value pairs specifying the column values to be inserted. The method will quote the table name properly and will use parameter-binding for the values to be inserted.
|
|
|
|
Noe that unlike the previous query methods which specify parts of a `SELECT` query, the `insert`, `update` and `delete` methods (the latter two are to be described shortly) specify a complete SQL statement.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
// INSERT INTO `tbl_user` (`name`, `email`) VALUES (:name, :email)
|
|
insert('tbl_user', array('name'=>'Tester', 'email'=>'tester@example.com'))
|
|
~~~
|
|
|
|
|
|
### update
|
|
|
|
~~~
|
|
[php]
|
|
function update($table, $columns, $conditions='', $params=array())
|
|
~~~
|
|
|
|
The [update|CDbCommand::update] method specifies an `UPDATE` SQL statement. The `$table` parameter specifies which table to be updated; `$columns` is an array of name-value pairs specifying the column values to be updated; `$conditions` and `$params` are like in [where|CDbCommand::where], which specify the `WHERE` clause in the `UPDATE` statement. The method will quote the table name properly and will use parameter-binding for the values to be updated.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
// UPDATE `tbl_user` SET `name`=:name WHERE id=:id
|
|
update('tbl_user', array('name'=>'Tester'), 'id=:id', array(':id'=>1))
|
|
~~~
|
|
|
|
|
|
### delete
|
|
|
|
~~~
|
|
[php]
|
|
function delete($table, $conditions='', $params=array())
|
|
~~~
|
|
|
|
The [delete|CDbCommand::delete] method specifies a `DELETE` SQL statement. The `$table` parameter specifies which table to be updated; `$conditions` and `$params` are like in [where|CDbCommand::where], which specify the `WHERE` clause in the `DELETE` statement. The method will quote the table name properly.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
// DELETE FROM `tbl_user` WHERE id=:id
|
|
delete('tbl_user', 'id=:id', array(':id'=>1))
|
|
~~~
|
|
|
|
|
|
Executing Queries
|
|
-----------------
|
|
|
|
After calling the above query builder methods to build a query, we can call the DAO methods as described in [Data Access Objects](/doc/guide/database.dao) to execute the query. For example, we can call [CDbCommand::queryRow()] to obtain a row of result, or [CDbCommand::queryAll()] to get all rows at once. Note that for `INSERT`, `UPDATE` and `DELETE` queries, we must use [CDbCommand::execute()] to execute them.
|
|
|
|
Below are some examples:
|
|
|
|
~~~
|
|
[php]
|
|
$users = Yii::app()->db->createCommand()
|
|
->select('*')
|
|
->from('tbl_user')
|
|
->queryAll();
|
|
|
|
Yii::app()->db->createCommand()
|
|
->insert('tbl_user', array(
|
|
'username' => 'tester',
|
|
'email' => 'tester@example.com',
|
|
))->execute();
|
|
~~~
|
|
|
|
|
|
Retrieving SQLs
|
|
---------------
|
|
|
|
Besides executing a query built by the Query Builder, we can also retrieve the corresponding SQL statement. This can be done by calling [CDbCommand::getText()].
|
|
|
|
~~~
|
|
[php]
|
|
$sql = Yii::app()->db->createCommand()
|
|
->select('*')
|
|
->from('tbl_user')
|
|
->getText();
|
|
~~~
|
|
|
|
If there are any parameters to be bound to the query, they can be retrieved via the [CDbCommand::params] property.
|
|
|
|
|
|
Alternative Syntax
|
|
------------------
|
|
|
|
Sometimes, using method chaining to build a query may not be the optimal choice. The Yii Query Builder allows a query to be built using simple object property assignments. In particular, for each query builder method, there is a corresponding property that has the same name. Assigning a value to the property is equivalent to calling the corresponding method. For example, the following two statements are equivalent, assuming `$command` represents a [CDbCommand] object:
|
|
|
|
~~~
|
|
[php]
|
|
$command->select(array('id', 'username'));
|
|
$command->select = array('id', 'username');
|
|
~~~
|
|
|
|
Furthermore, the [CDbConnection::createCommand()] method can take an array as the parameter. The name-value pairs in the array will be used to initialize the properties of the created [CDbCommand] instance. This means, we can use the following code to build a query:
|
|
|
|
~~~
|
|
[php]
|
|
$row = Yii::app()->db->createCommand(array(
|
|
'select' => array('id', 'username'),
|
|
'from' => 'tbl_user',
|
|
'where' => 'id=:id',
|
|
'params' => array(':id'=>1),
|
|
))->queryRow();
|
|
~~~
|
|
|
|
<div class="revision">$Id$</div> |