答案:
SQLite介绍(三) SQLite 迭代器
在 PHP 5.0 中,有另外一种方式来从查询中获得行数据,那就是运用迭代器.
$db = new SQLiteDatabase("db.sqlite");
// 执行非缓冲的查询可以减少内在的使用.
$res = $db->unbufferedQuery("SELECT * FROM foo");
foreach ($res as $row) { //迭代结果集对象
// 输出代码
print_r($row);
}?>
迭代对象的工作过程除了不需要要键值(’keys’)和用一个值来表示数组中所包含的特定的数据行之外,其它跟通过foreach()访问数组对象很相似.因为迭代器是内部引擎句柄而不是函数. 迭代器跟sqlite_fetch_*()函数比较用到的PHP代码就少得很多了.并且不需要把结果集缓冲到内存中.总之,迭代器是一种非常快速,但是简单易用的获取数据的方法.运用SQLite的对象迭代器,不会存在什么不足之处,当你需要遍历一个多行数据集时,你一定应该考虑使用它们.
工具函数
SQLite扩展也提供了一些在操作数据库时使用起来很方便的工具函数.其中一个就是sqlite_num_fields(), 可以用于获得一个特定的结果集中的字段数(列数).
当然,也有其它选择,如果你想取得数据的同时得到列数,你可以对数据集使用count()方法,就可以获得上面函数相同的数目.如果同时取回了字符串型和数字型的主键,你必须让结果一分为二,因为结果数组中的字段入口数会是字段数的两倍.如果你的脚本需要获得特定表的列名时,这个数目是很有用的.如果是这样的话,你就可以在一个循环中用sqlite_field_name()来获得字段名称信息.正如下例所示.[译者注,本例是PHP5的情况,用的是OO接口,在PHP4中,需要变换相对应的函数,具体请参见PHP Manual SQLite的参考一节]$db = new SQLiteDatabase("db.sqlite");
$res = $db->unbufferedQuery("SELECT * FROM foo LIMIT 1");
//取得字段数目
$n_fields = $res->numFields();
$i = 0;
while ($i < $n_fields) {
//获得单个字段名
$field_name = $res->fieldName($i++);
echo $field_name."\n";
}?>
很显然,这是获得表中列名的一种很理想的方式.很明显示地,当源表中没有任何行时,这个方式就会失败.并且这个方法取了一些你可能并不想用的数据,因此,一个更好的解决方法是用sqlite_fetch_column_types()函数.这具函数 会返回特定表的列和类型,而不管表中的数据量如何.
缓存优势
在很多情况下,由于性能和内存的原因,你可能想执行非缓冲查询.尽管如此,这存在在某种情况下所必须的轻微的功能损失.这也就说明为什么,非缓冲查询不总是最优的选择.
例如,假设你想知道你的查询到底取回了多少行数据.如果用非缓存查询的话,你必须一行行地查询,才能知道这个数目.而用缓存查询,只要不费吹灰之力地执行sqlite_num_rows()函数就可以了. 这就可以取回查询结果的行数.非缓存查询还仅限于线性数据获取,这就意味着你必须取得一系列中所有行的信息,一次一行.而对于缓存查询则没有这个限制.你可用sqlite_seek() 函数来到达任意一行,并且取回数据.只要需要,逆向地获取行数据也是可以的.
$db = new SQLiteDatabase("db.sqlite");
$res = $db->query("SELECT * FROM foo");
$n_rows = $res->numRows(); // 获得行数
$res->seek($n_rows - 1); // 到最后一行
// 返回获取数据
do {
$data = $res->current(SQLITE_ASSOC); // 获得行数据
print_r($data);
}
while ($res->hasPrev()&& $res->prev()); // 逆向前进,直到第一行?>
定制函数
SQLite扩展所带来的对表格操作的最有意思的特性之一是用SQL创建你自己的函数的能力.这可能得益于SQLite在同一个库中组合了数据库引擎和接口,而这个库又同PHP很好地耦合。通过使用sqlite_create_function(),你可以 构造能够运用于结果集或在WEHRE子句中使用的函数。
/* 此函数用于分别用户指定的字符串和数据库中字符串在包含的字符上的差异*/
function char_compare($db_str, $user_str) {
return similar_text($db_str, $user_str);
}$db = new SQLiteDatabase("db.sqlite");
/* 利用已有的PHP函数在SQLite内部创建char_compare()函数。 此调用的第3个参数指明创建的函数所需的参数数目*/
$db->createFunction('char_compare', 'char_compare', 2);
/* 执行包含char_compare()函数,并用其比较name和指定字符串的查询*/
$res = $db->arrayQuery("SELECT name, char_compare(name, 'Il2') AS sim_index FROM foo", SQLITE_ASSOC);print_r($res);
?>
用PHP内嵌SQL的能力,允许你简化实际的脚本,从而使更多的开发者来运用它。这个特性也允许PHP作为一个模块引擎,简化用数据库中数据来生成HTML结构的过程。在很多情况下,这能大大简化代码,以达到无须在PHP顶部放置一个模块系统。除了代码简化之外,这也提高了程序性能和减少脚本内存占用。因为无须在用户空间中进行数据处理。
注意,如果你运用的数据有可能包含二进制数据。在处理这些数据之前,你必须用sqlite_udf_decode_binary() 函数来对SQLite内部二进制编码进行解码。当你完成了之后,你必须用函数sqlite_udf_encode_binary()来对二进制数据进行编码,以在后面某个时候能在没有损坏的情况下正常使用它。
总结
至此,你已经明白SQLite如何工作,并且了解了它能提供什么.你可能在你当前或将来的应用程序中运用它.希望,这个简短的介绍能使你熟悉SQLite提供的功能,并不会对你以往对SQLite的好印象带来任何不良影响.
正好所有的工具一样,SQLite也有其强项和弱项.对于小型的,并且大部分操作为读取操作的应用程序,SQLite 提供了理想的解决方案.而对大型的频繁写入的应用,SQLite是不太合适的.这种限制是由于SQLite的单文件架构导致的.这种架构不允许你在服务器间多路访问,也不允许在写时对数据库加锁.
关于作者
Ilia Alshanetsky 已经从事Web应用程序开发超过7年了,其中大部分都是基于PHP的开发.在最近的几年里,他热忱地加入PHP的开发中来,并合作开发大量的扩展,包括SQLite.现在Ilia正在经营他自己的公司. Advanced Internet Designs Inc.,公司的业务主要是开发和支持一个开源论坛FUDforum的开发.
欲联系Ilia,可以通过电子邮件ilia@prohost.org