首页 > 代码库 > Yii 数据库相关操作
Yii 数据库相关操作
CDbConnection: 一个抽象数据库连接
CDbCommand: SQL statement
CDbDataReader: 匹配结果集的一行记录
CDbTransaction:数据库事务
访问数据库前需要建立数据库连接;使用DAO建立一个抽象数据库链接
1 $connection = new CDbConnection($dsn, $username, $password);2 $connection->active = true; // 只有激活了连接才可以使用3 $connection->active = false; // 关闭连接
CDbConnection继承自CApplicationComponent,所以他可以像组件一样在任何地方使用。因此可以这样访问
Yii::app()->db
执行SQL语句需要CDbCommand对象,而该对象由CdbConnection::createCommand()返回,因此
$connection=Yii::app()->db;$command=$connection->createCommand($sql);
如果SQL语句想要完全由自己写,可以这样
$newSQL = ‘SQL语句‘;$command->text=$newSQL;
CDbCommand对象有两个方法execute()用于非查询SQL执行,而query(),通俗的讲就是用于SELECT查询
execute()返回的是INSERT, UPDATE and DELETE操作受影响的记录行数
query()返回一个CDbDataReader对象,使用CDbDataReader对象可以遍历匹配结果集中的所有记录
$rowCount=$command->execute(); // execute the non-query SQL$dataReader=$command->query(); // execute a query SQL // 返回CDbDataReader对像$rows=$command->queryAll(); // query and return all rows of result$row=$command->queryRow(); // query and return the first row of result$column=$command->queryColumn(); // query and return the first column of result$value=$command->queryScalar(); // query and return the first field in the first row
query()返回的是代表结果集的对象而非直接的结果,因此要获取结果集的记录可以这样
$dataReader=$command->query();
// CDbDataReader::read()可以一次获取一行数据,到末尾时返回falsewhile(($row=$dataReader->read())!==false) {...}
// CDbDataReader实现了迭代器接口因此可以使用foreach遍历foreach($dataReader as $row) {...}
// 一次性返回所有的记录(数组)$rows=$dataReader->readAll();
queryXXX() 形式的方法会直接返回匹配的记录集合,当query()不是,他返回一个代表结果集的对象
YII中的CDbTransaction类用于事务
// 首先,建立一个连接$connection = Yii::app()->db;// 第二,开始事务$transaction=$connection->beginTransaction();// 第三,执行SQL,如果错误就抛出异常,在异常处理中回滚。try{ $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); //.... other SQL executions // 如果SQL执行都没有抛出异常,那就提交。 $transaction->commit(); } catch(Exception $e) { $transaction->rollBack(); // 在异常处理中回滚}
执行SQL中,一般都需要绑定一些用户参数,对于用户参数,需要防止SQL注入攻击
PDO对象的绑定参数的方法可以防止SQL注入攻击,同样扩展自PDO的DAO也有这样的功能
举例说明:
// 第一,建立一个连接:$connection = Yii::app()->db;// 第二,写下无敌的SQL语句,比如:$sql="INSERT INTO tbl_user (username, email) VALUES(:username,:email)";// 第三,创建CDbCommand对象用于执行SQL$command=$connection->createCommand($sql);// 接下来,将SQL语句中的形式参数,替换为实际参数$command->bindParam(":username",$username,PDO::PARAM STR); // 这与PDO有点不同,PDO中不带冒号$command->bindParam(":email",$email,PDO::PARAM STR); // 同样// 最后,执行$command->execute();// 如果还有其他的数据需要插入,可以再次绑定实参。
使用CDbDataReader对象的bindColumn()方法将结果集中的列绑定到PHP变量。
因此,读取一行记录,列值将自动填充到对应的PHP对象中
比如这样:
$connection = Yii::app()->db;$sql = "SELECT username, email FROM tbl_user";$dataReader = $connection->createCommand($sql)->query(); //很赞的方法链, 可惜不能接着.each()$dataReader->bindColumn(1, $username); //第一列值绑定到$username$dataReader->bindColumn(2, $email); //第二列值绑定到$email//接着循环读取并操作数据while( $dataReader->read() !== false ) { ... // 与先前的 while(($row=$dataReader->read())!==false) 有所不同哦!}
设置表前缀,使用 CDbConnection::tablePrefix 属性在配置文件中设置
// Yii实现了把一条完整的SQL语句完完全全肢解的能力,比如这样:$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(); //返回匹配的结果集的第一行
其实这条语句是这样的: $newSQL =‘SELECT id, username, profile from tbl_user u INNER JOIN tbl_profile p ON u.id = p.user_id WHERE u.id =:id‘
yii提供了一种构建SQL的机制(也就是说不用自己写长长的SQL)
首相要实例化一个CDbCommand对象
$command = Yii::app()->db->createCommand(); // 注意参数留空了。。
可用的方法列表如下:
->select(): SELECT子句->selectDistinct(): SELECT子句,并保持了记录的唯一性->from(): 构建FROM子句->where(): 构建WHERE子句->join(): 在FROM子句中构建INNER JOIN 子句->leftJoin(): 在FROM子句中构建左连接子句->rightJoin(): 在FROM子句中构建右连接子句->crossJoin(): 添加交叉查询片段(没用过)->naturalJoin(): 添加一个自然连接子片段->group(): GROUP BY子句->having(): 类似于WHERE的子句,但要与GROUP BY连用->order(): ORDER BY子句->limit(): LIMIT子句的第一部分->offset(): LIMIT子句的第二部分->union(): appends a UNION query fragment
select()默认返回全部列
// 但你可以这样:select(‘username, email‘);// 或使用表限定,或使用别名select(‘tbl_user.id, username name‘);// 或使用数组作为参数select(array(‘id‘, ‘count(*) as num‘));
from() 如果制定了多个表需要使用逗号分隔的字符串,就像原生SQL语句那样:
from(‘tbl_user, tbl_post, tbl_profile‘);// 当然,你也可以使用表别名, 还可以使用完整的数据库限定名from(‘tbl_user u, public.tbl_profile p‘);
WHERE子句
// 在where()中使用 ANDwhere(array(‘and‘, ‘id=:id‘, ‘username=:username‘), array(‘:id‘=>$id, ‘:username‘=>$username);// 在where()中使用 OR 与 AND用法相同,如下: ##看起来比直接写更加繁琐##where( array(‘and‘, ‘type=1‘, array(‘or‘, ‘id=:id‘,‘username=:username‘) ),array(‘:id‘=>$id, ‘:username‘=>$username ));
IN 操作符用法
where(array(‘in‘, ‘id‘, array(1,2,3)))
LIKE用法
where( array(‘like‘, ‘name‘, ‘%tester%‘) );where( array(‘like‘,‘name‘, array(‘%test%‘, ‘%sample%‘)) ) // 等于 name LIKE ‘%test%‘ AND name LIKE ‘%sample%// 再这样复杂下去, 使用这种方法简直是自杀行为。$keyword=$ GET[‘q‘];// escape % and characters$keyword=strtr($keyword, array(‘%‘=>‘n%‘, ‘ ‘=>‘n ‘));$command->where(array(‘like‘, ‘title‘, ‘%‘.$keyword.‘%‘));
添加了这么多,你都不知道合成后的SQL长啥样了,可以使用->text()查看(魔术方法)
如果觉得组合的SQL没有错误,那就执行他,添加->queryAll(); 这可以获得所有匹配的结果集。
当然,如果你确定执行的结果集中只有一行,可以添加->queryRow();来直接获取。
如果一个CDbCommand对象需要执行多次,那么在下一次执行之前记得调用reset();
$command = Yii::app()->db->createCommand();$users = $command->select(‘*‘)->from(‘tbl_users‘)->queryAll();$command->reset(); // clean up the previous query$posts = $command->select(‘*‘)->from(‘tbl_posts‘)->queryAll();
Yii 数据库相关操作