原文地址:http://www.yiiframework.com/doc/guide/1.1/en/database.query-builder
不过原文是英文的,Yii的官网没有翻译这一章,自己就尝试着翻译了一下,有很多地方时会按自己的理解写,不一定完全按原文翻译。。。
Yii的查询生成器提供了用面向对象的方式写SQL语句。它允许开发人员使用类的方法和属性来指定一个SQL语句的各个部分。然后,组装成一个有效的SQL语句,可以通过调用DAO数据访问对象的描述方法为进一步执行。以下显示了一个典型的使用查询生成器建立一个select语句:
$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语句。
注:查询生成器不能用于修改现有的查询指定为SQL语句。例如,下面的代码将不能工作:
$command = Yii::app()->db->createCommand('SELECT * FROM tbl_user');// the following line will NOT append WHERE clause to the above SQL$command->where('id=:id', array(':id'=>$id));
换句话说,不要混合使用普通的SQL和查询生成器。
1. 制备查询生成器(Preparing Query Builder)Yii的查询生成器是从 CDbCommand提供主要数据库查询类,描述数据访问对象。
开始使用查询生成器,我们创造了CDbCommand的一个新实例,
$command = Yii::app()->db->createCommand();
我们使用Yii::app()->db
来获得数据库连接,然后调用CDbConnection::createCommand()创建所需的命令实例。
请注意,将整个SQL语句放入 createcommand() ,叫做数据访问对象,我们需呀把设置它为空。这是因为我们将在下面的解释中使用查询生成器添加SQL语句的各个部分的方法。
2. 建立数据检索查询(Building Data Retrieval Queries)数据检索查询是指选择SQL语句。查询生成器提供了一套方法来建立一个SELECT语句的各个部分。因为所有这些方法返回CDbCommand的实例,我们可以使用方法链调用他们,如图所示,在本节开头的例子。
AND
OperatorOR
operator在下面,我们将解释如何使用这些查询生成器方法。为简单起见,我们假设底层数据库是MySQL。注意:如果你使用的是其他数据库,表/列/值引用的例子可能是不同的。
select()function select($columns='*')
该select()方法指定一个查询的选择部分。$columns参数指定要选择的列,它可以是一个字符串,用逗号分隔列,或者一个数组的列名称。列的名称可以包含表的前缀和 / 或列别名。该方法将自动引用列名,除非一列包含一些括号(这意味着这个列是一个DB的表达式)。
下面是一些例子:
// 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 numselect(array('id', 'count(*) as num'))selectDistinct()
function selectDistinct($columns)
selectdistinct()方法类似于select(),除了它打开了DISTINCT
的标志。例如,selectdistinct('id,用户名”)会产生以下SQL:
SELECT DISTINCT `id`, `username`from()
function from($tables)
from()方法指定来了一个查询的FROM部分。$tables
参数指定表的选择。这可以是一个字符串,用逗号分隔的表的名称,或表名数组。表的名称可以包含架构前缀(例如公共。tbl_user)和/或表的别名(e.g.tbl_user U)。该方法将自动引用表的名称,除非它包含一些括号(即表是一个给定的子查询或DB的表达式)。
下面是一些例子:
// 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) pfrom(array('tbl_user', '(select * from tbl_profile) p'))where()
function where($conditions, $params=array())
where()方法指定查询的WHERE。$conditions 参数指定查询条件的同时,$params 指定参数绑定到整个查询。$conditions参数可以是一个字符串(例如id =1)或一个数组中的格式:
array(operator, operand1, operand2, ...)
operator
可以是以下的任何一个:
and
: operands应该使用 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 操作,除了operands是使用 OR 连接的。
in
: operand 1应是一个列或DB表达式,而 operand 2是代表值的范围的数组,列或 DB 表达式应在这个数组的范围内。例如,array('in', 'id', array(1,2,3))
将生成id IN (1,2,3)
。
not in
: 类似 in 操作,除了用 NOT IN 代替 IN 去生成SQL。
like
: operand 1应是一个列或DB 表达式,而operand 2是代表值的范围的数组,列或 DB 表达式应在这个数组的范围内。例如,array('like', 'name', '%tester%')
会生成name LIKE '%tester%'
。当规定值的范围为一个数组时,多个 LIKE 生成SQL时会用 AND 连接。例如,array('like', 'name', array('%test%', '%sample%'))
会生成name LIKE '%test%' AND name LIKE '%sample%'
。
not like
:类似 like 的操作,除了用 NOT LIKE代替 LIKE 去生成SQL。
or like
: 类似 like 的操作,除了多个 like 生成 SQL 时用OR连接。
or not like
: 类似 not like 的操作,除了多个 like 生成 SQL 时用OR连接。
下面是一些例子,使用的地方:
// WHERE id=1 or id=2where('id=1 or id=2')// WHERE id=:id1 or id=:id2where('id=:id1 or id=:id2', array(':id1'=>1, ':id2'=>2))// WHERE id=1 OR id=2where(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时,我们必须明确指定的通配符(如%和_)的模式。如果参数是从用户的输入,我们也应该使用下面的代码转义特殊字符,以防止他们被当作通配符:
$keyWord=$_GET['q'];// escape % and _ characters$keyword=strtr($keyword, array('%'=>'\%', '_'=>'\_'));$command->where(array('like', 'title', '%'.$keyword.'%'));andWhere()
function andWhere($conditions, $params=array())
用 and 的方式添加到WHERE的条件中。此方法的行为几乎是 where() 相同,除了它只是添加条件不能取代它。在where()文档中有该方法参数的详细信息。
orWhere()function orWhere($conditions, $params=array())
用 or 的方式添加到WHERE的条件中。此方法的行为几乎是 where() 相同,除了它只是添加条件不能取代它。在where()文档中有该方法参数的详细信息。
order()function order($columns)
order() 方法指定查询的ORDER BY部分。$columns
参数指定列进行排序,这可以是一个包含用逗号分隔列和order的方向(ASC 或
DESC
)的字符串,或者一个列和order的方向的数组。列名称可以包含表前缀。该方法将自动引用列名,除非一列包含一些括号(即给出一个DB表达式)。
下面是一些例子:
// ORDER BY `name`, `id` DE