Yii的查询构造器提供了一个用面向对象的方法来构造SQL语句。他让开发人员可以用类的方法,属性来作为SQL语句的一部分。然后把不同部分组装到一个正确的SQL语句中,调用DAO的方法来执行。下面的例子演示如何用QB来构造SQL语句

  1. $user = Yii::app()->db->createCommand()
  2. ->select('id, username, profile')
  3. ->from('tbl_user u')
  4. ->join('tbl_profile p', 'u.id=p.user_id')
  5. ->where('id=:id', array(':id'=>$id))
  6. ->queryRow();

如果你是在程序里拼装SQL,或者是基于你的程序逻辑来拼装,那么QB就是最合适的。用QB的好处诸多:

●可以程序化的编写负责的SQL语句
●自动引用表名,列名,避免跟其他的关键词冲突
●引用参数banding的方法,防止SQL注入
●提供了抽象数据库,这可以让数据库迁移变得很简单。

QB的使用并非强制性的,实际上,如果你的查询非常的简单,那么直接写SQL语句更简单,也更快,没必要非得用QB。但是需要特别注意的一定,不要把QB跟纯的SQL混用。

1.1 准备QB

Yii QB 是在CDbCommand的选项里提供的。主要的查询类是在DAO里。

用QB之前,我们先实例化一个CDbCommand:

  1. $command = Yii::app()->db->createCommand();

这行代码里,我们用Yii::app()->db获取数据库连接,然后调用createCommand()创建所需要的命名对象。注意到上面我们调用createCommand时,参数是空的。之前DAO的时候是直接把SQL语句初始化进去。现在这里留空,是因为我们要用QB来构造SQL语句。

1.2 创建查询SQL

查询语句涉及到SELECT的语句,QB提供了一整套的方法来构造SELECT的每个部分。由于这些方法都返回的是CDbCommand句柄,所以我们在用的时候,可以用串链的方式来做,就像本节开篇的那样作法。具体的方法就不翻译了,节约时间

接下来,我们一一解释如何使用这些构造器的方法。为了简便,默认底层数据库是Mysql,如果你使用的是其他数据库,table/column/value 这些在接下来的例子中或许会有所不同。

select()

  1. function select($columns='*')

这个不解释了,列出一些例子。

  1. // SELECT *
  2. select()
  3. // SELECT `id`, `username`
  4. select('id, username')
  5. // SELECT `tbl user`.`id`, `username` AS `name`
  6. select('tbl user.id, username as name')
  7. // SELECT `id`, `username`
  8. select(array('id', 'username'))
  9. // SELECT `id`, count(*) as num
  10. select(array('id', 'count(*) as num'))

selectDistinct()

  1. function selectDistinct($columns)

这个就是在选择的时候,去掉重复的值。例如,selectDistinct('id, username') 就等同于SELECT DISTINCT `id`, `username`

from()

  1. function from($tables)

from这个方法用来指定查询的FROM部分。变量$tables指定了那些表将是用来选择的。这些表名可以用“,”隔开。表明也可以携带schema的前缀。

  1. // FROM `tbl user`
  2. from('tbl user')
  3. // FROM `tbl user` `u`, `public`.`tbl profile` `p`
  4. from('tbl user u, public.tbl profile p')
  5. // FROM `tbl user`, `tbl profile`
  6. from(array('tbl user', 'tbl profile'))
  7. // FROM `tbl user`, (select * from tbl profile) p
  8. from(array('tbl user', '(select * from tbl profile) p'))

where()

  1. function where($conditions, $params=array())

where这个方法,指定了查询中的WHERE这个部分。变量$conditions指定了查询条件,$params 指定了所有用到的变量。$conditions可以是一个简单的字符串(如id=1),也可以是一个数组的形式:

  1. array(operator, operand1, operand2, ...)

在上面的数组中,operator可以是以下的几种类型:

● 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: 同上
● in:第一项表示数据库的字段,第二项表示一个范围的数组。例如:array('in', 'id', array(1,2,3)) 等同于id IN (1,2,3)。
● not in:同上
● like:array('like', 'name', '%tester%')等同于nameLIKE '%tester%'
● not like:同上
● or like:跟like一致,只是为了连接多个like语句,加了一个or的操作符。
● or not like:同上

以下是一些具体的实例:

  1. // WHERE id=1 or id=2
  2. where('id=1 or id=2')
  3. // WHERE id=:id1 or id=:id2
  4. where('id=:id1 or id=:id2', array(':id1'=>1, ':id2'=>2))
  5. // WHERE id=1 OR id=2
  6. where(array('or', 'id=1', 'id=2'))
  7. // WHERE id=1 AND (type=2 OR type=3)
  8. where(array('and', 'id=1', array('or', 'type=2', 'type=3')))
  9. // WHERE `id` IN (1, 2)
  10. where(array('in', 'id', array(1, 2))
  11. // WHERE `id` NOT IN (1, 2)
  12. where(array('not in', 'id', array(1,2)))
  13. // WHERE `name` LIKE '%Qiang%'
  14. where(array('like', 'name', '%Qiang%'))
  15. // WHERE `name` LIKE '%Qiang' AND `name` LIKE '%Xue'
  16. where(array('like', 'name', array('%Qiang', '%Xue')))
  17. // WHERE `name` LIKE '%Qiang' OR `name` LIKE '%Xue'
  18. where(array('or like', 'name', array('%Qiang', '%Xue')))
  19. // WHERE `name` NOT LIKE '%Qiang%'
  20. where(array('not like', 'name', '%Qiang%'))
  21. // WHERE `name` NOT LIKE '%Qiang%' OR `name` NOT LIKE '%Xue%'
  22. where(array('or not like', 'name', array('%Qiang%', '%Xue%')))

注意,例如我们在用%或者是_这些特殊字符集的时候,要特别注意。如果这些模式是用户输入的,我们要用以下的方法来对待特殊字符:

  1. $keyword=$ GET['q'];
  2. // escape % and characters
  3. $keyword=strtr($keyword, array('%'=>'n%', ' '=>'n '));
  4. $command->where(array('like', 'title', '%'.$keyword.'%'));

order()

  1. function order($columns)

这些命令如果懂SQL的,都不需要解释了,不懂的去补习。后面的开始只给例子了。

  1. // ORDER BY `name`, `id` DESC
  2. order('name, id desc')
  3. // ORDER BY `tbl profile`.`name`, `id` DESC
  4. order(array('tbl profile.name', 'id desc'))

limit() and o set()

  1. function limit($limit, $offset=null)
  2. function offset($offset)

例子:

  1. // LIMIT 10
  2. limit(10)
  3. // LIMIT 10 OFFSET 20
  4. limit(10, 20)
  5. // OFFSET 20
  6. offset(20)

join() and its variants

  1. function join($table, $conditions, $params=array())
  2. function leftJoin($table, $conditions, $params=array())
  3. function rightJoin($table, $conditions, $params=array())
  4. function crossJoin($table)
  5. function naturalJoin($table)

例子

  1. // JOIN `tbl profile` ON user id=id
  2. join('tbl profile', 'user id=id')
  3. // LEFT JOIN `pub`.`tbl profile` `p` ON p.user id=id AND type=1
  4. leftJoin('pub.tbl profile p', 'p.user id=id AND type=:type', array(':type'=>1))

group()

  1. function group($columns)

例子

  1. // GROUP BY `name`, `id`
  2. group('name, id')
  3. // GROUP BY `tbl profile`.`name`, `id`
  4. group(array('tbl profile.name', 'id')

having()

  1. function having($conditions, $params=array())

例子

  1. // HAVING id=1 or id=2
  2. having('id=1 or id=2')
  3. // HAVING id=1 OR id=2
  4. having(array('or', 'id=1', 'id=2'))

union()

  1. function union($sql)

例子

  1. // UNION (select * from tbl profile)
  2. union('select * from tbl profile')

执行语句

在用上面的这些构造器方法,构造好SQL后,我们可以调用DAO来执行语句了。例如我们可以调用CDbCommand::queryRow()获取第一个符合结果的记录,也可以用CDbCommand::queryAll()来一次性获取所有的查询结果。例如:

  1. $users = Yii::app()->db->createCommand()
  2. ->select('*')
  3. ->from('tbl user')
  4. ->queryAll();

访问SQL

除了执行构造器组装的SQL语句外,我们也可以调用CDbCommand::getText()来获取当前的SQL语句:

  1. $sql = Yii::app()->db->createCommand()
  2. ->select('*')
  3. ->from('tbl user')
  4. ->text;

如果查询中有用到变量,可以使用CDbCommand::params来读取属性。

QB的语法替换

有时候,用QB的方法链构造语句并不是最好的方法。Yii 的QB提供了用简单对象赋值的方法。特别是在每个查询构造方法中都有相同名字的时候。给属性值就跟调用方法是一样的。例如,下面的两个例子效果是一样的。

  1. $command->select(array('id', 'username'));
  2. $command->select = array('id', 'username');

甚至说,CDbConnection::createCommand()都可以用数组来做参数!这意味着我们可以按照下面的方法来执行(本人觉得不是很好的习惯,不知道什么特定的情况需要这样搞)

  1. $row = Yii::app()->db->createCommand(array(
  2. 'select' => array('id', 'username'),
  3. 'from' => 'tbl user',
  4. 'where' => 'id=:id',
  5. 'params' => array(':id'=>1),
  6. ))->queryRow();

创建多次查询

一个CDbCommand的对象,可以用来多次执行查询动作。在执行新的查询语句之前,必须要调用CDbCommand::reset()先清除之前的查询语句。

  1. $command = Yii::app()->db->createCommand();
  2. $users = $command->select('*')->from('tbl users')->queryAll();
  3. $command->reset(); // clean up the previous query
  4. $posts = $command->select('*')->from('tbl posts')->queryAll();

1.3 创建数据操作语句

操作语句就是增删改,会对数据库的数据进行更改的操作。具体就不介绍太多了

● insert(): inserts a row into a table
● update(): updates the data in a table
● delete(): deletes the data from a table

insert()

  1. function insert($table, $columns)
  1. // build and execute the following SQL:
  2. // INSERT INTO `tbl user` (`name`, `email`) VALUES (:name, :email)
  3. $command->insert('tbl user', array(
  4. 'name'=>'Tester',
  5. 'email'=>'tester@example.com',
  6. ));

update()

  1. function update($table, $columns, $conditions='', $params=array())
  1. // build and execute the following SQL:
  2. // UPDATE `tbl user` SET `name`=:name WHERE id=:id
  3. $command->update('tbl user', array(
  4. 'name'=>'Tester',
  5. ), 'id=:id', array(':id'=>1));

delete()

  1. function delete($table, $conditions='', $params=array())
  1. // build and execute the following SQL:
  2. // DELETE FROM `tbl user` WHERE id=:id
  3. $command->delete('tbl user', 'id=:id', array(':id'=>1));

1.4 创建SML查询(好像按照常规的分应该是属于DDL)

除了DML的操作以外,QB也提供了一些操作数据库架构的方法。主要有以下几种

  1. ● createTable(): creates a table
  2. ● renameTable(): renames a table
  3. ● dropTable(): drops a table
  4. ● truncateTable(): truncates a table
  5. ● addColumn(): adds a table column
  6. ● renameColumn(): renames a table column
  7. ● alterColumn(): alters a table column
  8. ● dropColumn(): drops a table column
  9. ● createIndex(): creates an index
  10. ● dropIndex(): drops an index

抽象数据类型

Yii QB 提供了一些抽象数据类型,可以用来定义表的字段类型。不像传统的底层数据库系统类型,这些抽象数据类型是独立于底层数据库的。当用抽象数据类型来定义字段类型的时候,QB在执行的时候,会自动转换为底层数据库的物理类型。

QB提供的数据类型包括

  1. pk: a generic primary key type, will be converted into int(11) NOT NULL AUTO
  2. INCREMENT PRIMARY KEY for MySQL;
  3. string: string type, will be converted into varchar(255) for MySQL;
  4. text: text type (long string), will be converted into text for MySQL;
  5. integer: integer type, will be converted into int(11) for MySQL;
  6. float:
  7. oating number type, will be converted into float for MySQL;
  8. decimal: decimal number type, will be converted into decimal for MySQL;
  9. datetime: datetime type, will be converted into datetime for MySQL;
  10. timestamp: timestamp type, will be converted into timestamp for MySQL;
  11. time: time type, will be converted into time for MySQL;
  12. date: date type, will be converted into date for MySQL;
  13. binary: binary data type, will be converted into blob for MySQL;
  14. boolean: boolean type, will be converted into tinyint(1) for MySQL;
  15. money: money/currency type, will be converted into decimal(19,4) for MySQL. This
  16. type has been available since version 1.1.8.

题外话,这些都是基本的SQL,用的时候翻一下手册就可以了。都是很好理解的。

createTable()

  1. function createTable($table, $columns, $options=null)
  1. // CREATE TABLE `tbl user` (
  2. // `id` int(11) NOT NULL AUTO INCREMENT PRIMARY KEY,
  3. // `username` varchar(255) NOT NULL,
  4. // `location` point
  5. // ) ENGINE=InnoDB
  6. createTable('tbl user', array(
  7. 'id' => 'pk',
  8. 'username' => 'string NOT NULL',
  9. 'location' => 'point',
  10. ), 'ENGINE=InnoDB')

renameTable()

  1. function renameTable($table, $newName)
  1. // RENAME TABLE `tbl users` TO `tbl user`
  2. renameTable('tbl users', 'tbl user')

dropTable()

  1. function dropTable($table)
  1. // DROP TABLE `tbl user`
  2. dropTable('tbl user')

truncateTable()

  1. function truncateTable($table)
  1. // TRUNCATE TABLE `tbl user`
  2. truncateTable('tbl user')

addColumn()

  1. function addColumn($table, $column, $type)
  1. // ALTER TABLE `tbl user` ADD `email` varchar(255) NOT NULL
  2. addColumn('tbl user', 'email', 'string NOT NULL')

dropColumn()

  1. function dropColumn($table, $column)
  1. // ALTER TABLE `tbl user` DROP COLUMN `location`
  2. dropColumn('tbl user', 'location')

renameColumn()

  1. function renameColumn($table, $name, $newName)
  1. // ALTER TABLE `tbl users` CHANGE `name` `username` varchar(255) NOT NULL
  2. renameColumn('tbl user', 'name', 'username')

alterColumn()

  1. function alterColumn($table, $column, $type)
  1. // ALTER TABLE `tbl user` CHANGE `username` `username` varchar(255) NOT NULL
  2. alterColumn('tbl user', 'username', 'string NOT NULL')

addForeignKey()

  1. function addForeignKey($name, $table, $columns,
  2. $refTable, $refColumns, $delete=null, $update=null)
  1. // ALTER TABLE `tbl profile` ADD CONSTRAINT `fk profile user id`
  2. // FOREIGN KEY (`user id`) REFERENCES `tbl user` (`id`)
  3. // ON DELETE CASCADE ON UPDATE CASCADE
  4. addForeignKey('fk profile user id', 'tbl profile', 'user id',
  5. 'tbl user', 'id', 'CASCADE', 'CASCADE')

dropForeignKey()

  1. function dropForeignKey($name, $table)
  1. // ALTER TABLE `tbl profile` DROP FOREIGN KEY `fk profile user id`
  2. dropForeignKey('fk profile user id', 'tbl profile')

createIndex()

  1. function createIndex($name, $table, $column, $unique=false)
  1. // CREATE INDEX `idx username` ON `tbl user` (`username`)
  2. createIndex('idx username', 'tbl user')

dropIndex()

  1. function dropIndex($name, $table)
    1. // DROP INDEX `idx username` ON `tbl user`
    2. dropIndex('idx username', 'tbl user')

数据库之Query Builder的更多相关文章

  1. Yii的学习(3)--查询生成器 (Query Builder)

    原文地址:http://www.yiiframework.com/doc/guide/1.1/en/database.query-builder 不过原文是英文的,Yii的官网没有翻译这一章,自己就尝 ...

  2. yii Query Builder (yii 查询构造器) 官方指南翻译

    /**** Query Builder translated by php攻城师 http://blog.csdn.net/phpgcs Preparing Query Builder 准备 Quer ...

  3. Yii2 三层设计模式:SQL Command、Query builder、Active Record(ORM)

    用Yii2也有一段时间了,发现Yii2 Framework对Database的操作有非常良好的结构和弹性. 接下来介绍三种数据库操作方式. SQL Command Level: // Get DB c ...

  4. [Laravel] 03 - DB facade, Query builder & Eloquent ORM

    连接数据库 一.Outline 三种操作数据库的方式. 二.Facade(外观)模式 Ref: 解读Laravel,看PHP如何实现Facade? Facade本质上是一个“把工作推给别人做的”的类. ...

  5. Laravel Query Builder 复杂查询案例:子查询实现分区查询 partition by

    案例 案例:Laravel 在文章列表中附带上前10条评论?,在获取文章列表时同时把每个文章的前10条评论一同查询出来. 这是典型分区查询案例,需要根据 comments 表中的 post_id 字段 ...

  6. SqlKata - 方便好用的 Sql query builder

    SqlKata查询生成器是一个用C# 编写的功能强大的Sql查询生成器.它是安全的,与框架无关.灵感来源于可用的顶级查询生成器,如Laravel Query Builder和 Knex. SqlKat ...

  7. [moka同学笔记]Yii2 数据操作Query Builder 2

    Query Builder $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name']) ->from('zs_dynast ...

  8. [moka同学笔记]Yii2 数据操作Query Builder

    Query Builder [php] view plain copy   $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name ...

  9. Yii2 数据操作Query Builder(转)

    Query Builder $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name']) ->from('zs_dynast ...

随机推荐

  1. openstack stein部署手册 8. neutron-api

    # 建立数据库用户及权限 create database neutron; grant all privileges on neutron.* to neutron@'localhost' ident ...

  2. 剖析 Vue.js 内部运行机制 (1)

    1. new Vue() 之后. Vue 会调用 _init 函数进行初始化,也就是这里的 init 过程,它会初始化生命周 期.事件. props. methods. data. computed ...

  3. bzoj5084 hashit 广义SAM+树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5084 题解 考虑平常对于静态问题,我们应该如何用 SAM 求本质不同的子串个数. 对于一个常规 ...

  4. vue项目中router路由配置

    介绍 路由:控制组件之间的跳转,不会实现请求.不用页面刷新,直接跳转-切换组件>>> 安装 本地环境安装路由插件vue-router:    cnpm install vue-rou ...

  5. rm 或者ls 报Argument list too long

    一个文件夹下面碎文件太多,rm 或者 ls的时候报 Argument list too long 解决办法: find /tmp -type d -name "*-*-" -del ...

  6. Atcoder2134 Zigzag MST

    问题描述 We have a graph with N vertices, numbered 0 through N−1. Edges are yet to be added. We will pro ...

  7. [洛谷 P1013] NOIP1998 提高组 进制位

    问题描述 著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字. 例如: L K V E L L K V E K K V E KL V V E KL KK E E K ...

  8. git本地创建一个分支并上传到远程服务器上

    git branch 查看分支 新建分支:git checkout -b dev 把新建的本地分支push到远程服务器 git push origin 本地名字:外地名字 删除远程分支 git pus ...

  9. JavaScript 复杂判断的更优雅写法借鉴

    前言: 我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得 ...

  10. Webstorm软件快捷键

    默认配置-Eclipse的常用快捷键对照表 查找/代替 Webstorm快捷键 Eclipse快捷键 说明 ctrl+shift+N ctrl+shift+R 通过文件名快速查找工程内的文件(必记) ...