YII访问数据库

CDbConnection: 一个抽象数据库连接
CDbCommand: SQL statement
CDbDataReader: 匹配结果集的一行记录
CDbTransaction:数据库事务 访问数据库前需要建立数据库连接;使用DAO建立一个抽象数据库链接:
$connection = new CDbConnection($dsn, $username, $password);
$connection->active = true; // 只有激活了连接才可以使用
// 想要关闭连接,可以这样:
$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()可以一次获取一行数据,到末尾时返回false
while(($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')); // 使用form() 如果制定了多个表需要使用逗号分隔的字符串,就像原生SQL语句那样:
from('tbl_user, tbl_post, tbl_profile');
// 当然,你也可以使用表别名, 还可以使用完整的数据库限定名
from('tbl_user u, public.tbl_profile p'); WHERE子句
// 在where()中使用 AND
where(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的SQL构建函数就是一鸡肋。 // Active Record
// 使用AR以面向对象的方式访问数据库,AR实现了ORM技术
// 当Post类表示表tbl_post时,我们可以使用这样的方式插入一条数据
$post = new Post();
$post->title = 'new title';
$post->content = 'new content';
$post->save(); // 保存即插入 // AR最典型的功能就是执行CRUD操作
// DAO定位于解决复杂的数据库查询,而AR定位于解决简单的数据库查询
// 一个AR类代表一张数据表,而一个AR对象代表表中的一行真实的记录,AR类继承CActiveRecord。
// 如果有一张POST表`tbl_post`,你可以这样定义一个AR类
class Post extends CACtiveRecord
{
public static function model($className = __CLASS__)
{
return parent::model($className);
} public function tablName()
{
return '{{post}}';
}
} // 表中的每一个字段都由AR类中的一个属性表示,如果试图通过属性访问表中没有字段,将会抛出一个异常。 // 一个AR一定需要一个主键,如果某张表没有主键,你就自己在类中伪造一个,像这样:
public function primaryKey()
{
return 'id'; // 'id' 是关联表中的一个字段,但他不是主键,现在将它指定为主键
} // 实例化一个AR,填写信息(类似于填充用户提交的信息),然后保存
$post = new Post;
$post->title = 'sample post';
$post->content = 'content for the sample post';
$post->create_time = time();
$post->save(); // 保存/插入 // 通过AR读取记录 fine() findByPk() findByAttributes() findBySql()
$post=Post::model()->find($condition,$params); // 返回Post对象(如果有匹配记录的话), 否则返回NULL
$post=Post::model()->findByPk($postID,$condition,$params);
$post=Post::model()->findByAttributes($attributes,$condition,$params);
$post=Post::model()->findBySql($sql,$params); // find()的一个例子:
$post=Post::model()->find('postID=:postID', array(':postID'=>10));
// 如果查询条件很是复杂,就要使用CDbCriteria类
$criteria = new CDbCriteria;
$criteria->select='title';
$creteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // 不需要第二个参数
// 另一种更好的写法
$post=Post::model()->find(array(
'select' => 'title',
'condition' => 'postID=:postID',
'params' => array(':postID' => 10)
)); // 如果查找的是多行记录可以使用 findAll() findAllByPk() findAllByAttributes() findAllBySql()
// find all rows satisfying the specified condition
$posts=Post::model()->findAll($condition,$params);
// find all rows with the specified primary keys
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// find all rows with the specified attribute values
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// find all rows using the specified SQL statement
$posts=Post::model()->findAllBySql($sql,$params);
// 如果没有匹配的行,将返回一个空数组,这可以用empty()去检测 // 另外的一些可以使用的方法:
// get the number of rows satisfying the specified condition
$n=Post::model()->count($condition,$params);
// get the number of rows using the specified SQL statement
$n=Post::model()->countBySql($sql,$params);
// check if there is at least a row satisfying the specified condition
$exists=Post::model()->exists($condition,$params); // 使用AR更新记录
// 一个典型的实例:
$post=Post::model()->findByPk(10);
$post->title='new post title';
$post->save(); // save the change to database
// 怎么知道这是一条新纪录还是一条旧的记录呢?使用如下方法:
if( CActiveRecord::isNewRecord )
// update the rows matching the specified condition
Post::model()->updateAll($attributes,$condition,$params);
// update the rows matching the specified condition and primary key(s)
Post::model()->updateByPk($pk,$attributes,$condition,$params);
// update counter columns in the rows satisfying the specified conditions
Post::model()->updateCounters($counters,$condition,$params); // 删除记录
$post=Post::model()->findByPk(10); // assuming there is a post whose ID is 10
$post->delete(); // delete the row from the database table
// 注意,当删除记录之后,$post仍然可用, 且保留了原始数据。
// 类级别的方法
// delete the rows matching the specified condition
Post::model()->deleteAll($condition,$params);
// delete the rows matching the specified condition and primary key(s)
Post::model()->deleteByPk($pk,$condition,$params); // 数据验证
// 将用户提交的数据保存到AR对象中
$post->title = $_POST['title'];
$post->content = $_POST['content'];
$post->save(); // assume $ POST['Post'] is an array of column values indexed by column names
$post->attributes=$ POST['Post'];
$post->save(); // RAR:Relatived Actie Record
// RAR本质上就是执行关系数据查询 // 如何让一个AR关联另一个AR
// 4中关系类型
self::BELONGS_TO
self::HAS_MANY
self::HAS_ONE
self::MANY_MANY 关系名称(关系类型,要关联的类名,外键名,其他额外的选项);
// 定义表关系 类:Post
public function relations()
{
return array(
'author'=>array(self::BELONGS_TO, 'User', 'author_id'), // 返回User对象
'categories'=>array(self::MANY_MANY, 'Category', 'tbl_post_category(post_id, category_id)'),
);
}
// 类:User
public function relations()
{
return array(
'posts' => array(self::HAS_MANY, 'Post', 'author_id'),
'profile' => array(self::HAS_ONE, 'Profile', 'owner_id')
);
} // 定义了AR间的关系之后,当执行关系查询时,与AR关联的AR也会自动实例化, 比如这样:
$author = User::model()->findByPk(1);
$author->posts; // posts关系已经定义。 // 执行关系查询
1).lazy loading approach 懒惰关系执行
// retrieve the post whose ID is 10
$post=Post::model()->findByPk(10);
// retrieve the post's author: a relational query will be performed here
$author=$post->author; // 如果先前没有执行过,现在才执行这个关系查询(事情拖到这一步才做,真的是很懒啊!) // 如果关系查询执行后没有匹配的结果,返回将会是NULL或空的数组。 2).eager loading approach 热心的关系查询 //这名字真的很萌!
// 也就是说一次性取回所有你想要的记录。管你要不要,这这这,太热心了吧!
$posts=Post::model()->with('author')->findAll();
// SQL => 'SELECT tbl_post.*, author.* FROM tbl_post t INNER JOIN tbl_user author ON t.author = tbl_user.id' $posts=Post::model()->with('author','categories')->findAll();
// SQL => 'SELECT * FROM tbl_post t INNER JOIN tbl_user u ON t.author = u.id INNER JOIN categories c ON t.id = c.post_id' $posts=Post::model()->with(
'author.profile',
'author.posts',
'categories')->findAll(); $criteria=new CDbCriteria;
$criteria->with=array(
'author.profile',
'author.posts',
'categories',
);
$posts=Post::model()->findAll($criteria);
或者
$posts=Post::model()->findAll(array(
'with'=>array(
'author.profile',
'author.posts',
'categories',
)
); // 如果我们想知道用户中谁发过帖子,并且帖子的状态是“公开”。我们并不关心用户发表过的帖子的内容。
$user = User::model()->with('posts')->findAll();
'VS'
$user = User::model()->with(array(
'posts' => array(
'select' => false,
'joinType' => 'INNER JOIN',
'condition' => 'posts.published = 1'
),
)
)->findAll();
// 返回的将会是所有发过帖子(且帖子已经公开)的用户 // 在relatinos()中定义更加复杂的关系
class User extends CActiveRecord
{
public function relations()
{
return array(
'posts'=>array(self::HAS MANY, 'Post', 'author id',
'order'=>'posts.create time DESC',
'with'=>'categories'),
'profile'=>array(self::HAS ONE, 'Profile', 'owner id'),
);
}
} // 利用别名解决歧义
$posts=Post::model()->with('comments')->findAll(array(
'order'=>'t.create time, comments.create time'
)); // Dynamic Relational Query 动态关系SQL查询,更改默认插叙条件:
User::model()->with(array(
'posts'=>array('order'=>'posts.create time ASC'),
'profile',
))->findAll(); $user=User::model()->findByPk(1);
$posts=$user->posts(array('condition'=>'status=1')); // 返回的都是AR对象, 而不是数据 // 统计查询
class Post extends CActiveRecord
{
public function relations()
{
return array(
'commentCount'=>array(self::STAT, 'Comment', 'post_id'),
'categoryCount'=>array(self::STAT, 'Category', 'post_category(post_id, category_id)'),
);
}
}

From: http://blog.csdn.net/cdefu/article/details/6973922

YII访问数据库的更多相关文章

  1. C#使用ADO.NET访问数据库(一)

    博主好久没更新博客了,最近有点忙(打麻将0.0..),今天更新一篇C#的,我还是想坚持更新博客,分享一下自己的心得,闲话少说,开始正题~~ ADO.NET概述:ADO.NET的作用在于他是客户端访问服 ...

  2. Android 异步任务,通过PHP访问数据库,多线程,线程间通讯

    文章列表MainActivity.java package com.eric.asynctask; import java.io.IOException; import java.util.Array ...

  3. ADO.NET 访问数据库

    对数据库的访问时各种数据库应用程序开发的核心技术,.NET框架中提出的ADO.NET技术为应用程序的开发提供了一致的接口,增强了程序的可移植性和可扩展性. a:使用链接对象Connection连接数据 ...

  4. 如何通过JDBC访问数据库

    Java数据库连接(JDBC)用与在Java程序中实现数据库操作功能,它提供了执行SQL语句.访问各种数据库的方法,并为各种不同的数据库提供统一的操作接口,java.sql包中包含了JDBC操作数据库 ...

  5. (转)发布Silverlight+WCF程序到IIS后,客户端访问数据库失败的解决方案

    转自url:http://greatverve.cnblogs.com/archive/2011/11/30/silverlight-wcf-pub.html 我们在编写Silverlight程序时, ...

  6. 在 Mac OS X 上创建的 .NET 命令行程序访问数据库 (使用Entity Framework 7 )

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  7. Entity FrameWork 中使用Lambda访问数据库性能优化

    在使用Entity Framework 访问数据库时,我们经常使用Lambda表达式,但是如果不小心的话,很容易就掉到坑里了.比如下面的例子:用Lambda访问MSSqlServer中的NewsInf ...

  8. sqlserver 服务器主体 无法在当前安全上下文下访问数据库

    今天使用sqlserver,发现了一个问题,就是使用 insert into 数据库名.dbo.表名(字段) values(值) 这样语句的时候,会返回错误: sqlserver 服务器主体 无法在当 ...

  9. IOS 使用FMDB多线程访问数据库 及databaseislocked的问题

    原理:文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写.在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译s ...

随机推荐

  1. C#操作mongodb数据库

    1.下载驱动: 如下图:选择c#解决方案,右键,点击 “管理NuGet程序包(N)...” 在弹出的对话框中,输入MongoDB.Driver,进行搜索,然后选择安装. 2.引用命名空间: using ...

  2. 使用Yeoman搭建 AngularJS 应用 (2) —— 让我们搭建一个网页应用

    原文地址:http://yeoman.io/codelab/index.html 使用Yeoman搭建简单的应用 今天将会搭建一个简单的网页程序.你将可以添加,删除,拖拽和保存. 浏览Yeoman Y ...

  3. c++中的static关键字

    1.在函数体中,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变. 2.在模块内(但在函数外),比如在某一个C源文件内,一个被声明为静态的变量可以被该模块内的所有函数调用,但不能被模块外的函 ...

  4. map(function, sequence)

    map(function, sequence) :对sequence中的item依次执行function(item),见执行结果组成一个List返回: >>> lt = range( ...

  5. USB CDC类

    现代嵌入式系统中,异步串行通信接口往往作为标准外设出现在单片机和嵌入式系统中.但是随着个人计算机通用外围设备越来越少地使用串口,串口正在逐渐从个人计算机特别是便携式电脑上消失.于是嵌入式开发人员常常发 ...

  6. Python和C|C++的混编(一):Python调用C、C++---Boost库

    不使用boost.python库来直接构建dll的话比较繁琐,下面实例是借助boost库实现python对C.C++的调用 1 首先确定已经安装python和boost库,本例测试环境是python2 ...

  7. NuGet学习笔记(1)——初识NuGet及快速安装使用

    关于NuGet园子里已经有不少介绍及使用经验,本文仅作为自己研究学习NuGet一个记录. 初次认识NuGet是在去年把项目升级为MVC3的时候,当时看到工具菜单多一项Library Package M ...

  8. 【HDOJ】2062 Subset sequence

    这道题目非常好,饶了点儿圈子.我的思路是,先按照组排列.例如,1            2           31 2         2 1        3 11 2 3      2 1 3  ...

  9. Virtual member call in a constructor

    http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor (Assuming you're writ ...

  10. php include include_once require require_once 的区别与联系

    一.require 与 include 的区别: The require() function is identical to include(), except that it handles er ...