SQLite in PHP
BinzyWu@phpe / 文
关键词: SQLite, MySQL, PHP4, PHP5, Pear, 触发器, 视图, SQL
(一) SQLite介绍
SQLite第一个Alpha版本诞生于2000年5月. 至今已经有4个年头了. 而在今年的5月SQLite也迎来了一个新的里程: SQLite 3.
下面是你访问SQLite官方网站: www.sqlite.org 时第一眼看到关于SQLite的特性.
1. ACID事务
2. 零配置 – 无需安装和管理配置
3. 储存在单一磁盘文件中的一个完整的数据库
4. 数据库文件可以在不同字节顺序的机器间自由的共享
5. 支持数据库大小至2TB
6. 足够小, 大致3万行C代码, 250K
7. 比一些流行的数据库在大部分普通数据库操作要快
8. 简单, 轻松的API
9. 包含TCL绑定, 同时通过Wrapper支持其他语言的绑定
10. 良好注释的源代码, 并且有着90%以上的测试覆盖率
11. 独立: 没有额外依赖
12. Source完全的Open, 你可以用于任何用途, 包括出售它
从代码架构图你可以轻松的看出, 是的, SQLite非常简单. 对, SQLite的设计思想就是简单:
1. 简单的管理
2. 简单的操作
3. 简单的在程序中使用它
4. 简单的维护和客制化
因为简单所以它快速, 但虽然简单, 却仍非常可靠. 适合SQLite的应用场所有, 网站,嵌入式设备和应用, 应用程序文件格式, 代替特别的文件, 内部或临时数据库, 命令行数据集分析工具, 在演示或测试中代替企业级数据库, 数据库教学, 试验SQL语言扩展等. 但并不是所有都合适, 比如在使用Server/Client结构的时候,高负荷的网站,高并发等情况下并不建议使用SQLite.
本文重点在于介绍SQLite在PHP中的应用, PHP作为Web应用中一个重要力量一直在不断的前进和发展. 在马上就要Release的PHP的第五个版本中, 不再将MySQL作为默认支持, 而转为将SQLite的扩展作为默认支持. 从某种程度上说MySQL的广泛应用有PHP的很大功劳. 虽然说PHP改变默认支持有MySQL的授权改变的原因, 但选择SQLite也是有原因的, 理由就在于上面所提到的那些特性. 其实MySQL从来就不是完全免费的, 你无法用于商业用途. 而SQLite是完全的open的.
(二) SQLite SQL
SQLite的SQL从很大程度上实现了ANSI SQL92标准. 特别的SQLite支持视图, 触发器, 事务, 支持嵌套SQL. 这些都会在下面应用的过程中讲到, 故这边先暂时放下, 而主要说说SQLite所不支持的一些SQL.
1. 不支持Exists, 虽然支持in(in是Exists的一种情况)
2. 不支持多数据库, 如: create table db1.table1 as select * from db2.table1;
3. 不支持存储过程
4. 不支持Alter View/Trigger/Table
5. 不支持Truncate, 在SQLite中Delete不带Where字句时和Truncate的效果是一样的.
6. 不支持Floor和Ceiling函数, 还有其他蛮多的函数
7. 没有Auto Increment(自增)字段, 但是SQLite其实是支持Auto Increment的, 即在将该字段设置为” INTEGER PRIMARY KEY”的时候.
8. 不支持If Exists
……
详细的SQL支持可以访问: http://www.sqlite.org/lang.htm
详细的不支持SQL可以访问: http://www.sqlite.org/cvstrac/wiki?p=UnsupportedSql
(三) SQLite的数据类型
首先你会接触到一个让你惊讶的名词: Typelessness(无类型). 对! SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 无论这列声明的数据类型是什么(只有在一种情况下不是, 稍后解释). 对于SQLite来说对字段不指定类型是完全有效的. 如:
Create Table ex1(a, b, c); |
诚然SQLite允许忽略数据类型, 但是仍然建议在你的Create Table语句中指定数据类型. 因为数据类型对于你和其他的程序员交流, 或者你准备换掉你的数据库引擎. SQLite支持常见的数据类型, 如:
CREATE TABLE ex2( a VARCHAR(10), b NVARCHAR(15), c TEXT, d INTEGER, e FLOAT, f BOOLEAN, g CLOB, h BLOB, i TIMESTAMP, j NUMERIC(10,5) k VARYING CHARACTER (24), l NATIONAL VARYING CHARACTER(16) ); |
前面提到在某种情况下, SQLite的字段并不是无类型的. 即在字段类型为”Integer Primary Key”时.
(四) SQLite的Wrapper
由于SQLite有别于其他数据库引擎的TCP/IP或RPC访问方式, 完全地是本地的操作, 从某种角度来说你可以说SQLite和MS的Access很相似, 但是更小更强大. 所谓Wrapper即使对SQLite提供的接口进行封装, 使其他语言可以访问, 使用SQLite.
SQLite本身是提供C和Tcl的接口的. 所以可以非常轻易的和PHP相结合. 除了PHP的Wrapper以外, 还有许多世界各地的程序员提供了各种语言的SQLite的接口封装, 如Python, C++, Java, .Net…… 所流行的语言基本都有.
(五) PHP的环境下使用SQLite
1. PHP下的安装
在PHP5中, SQLite已作为默认支持的模块.在PHP4中你需要进行安装. 首先去http://pecl.php.net/package/SQLite 去下载到SQLite的扩展, 注意Windows下的版本需要去http://snaps.php.net/win32/PECL_STABLE/php_sqlite.dll 下载, 当然你也可以下载代码自己编译.事实上在linux下只需要使用命令: ‘pear install sqlite’就可以完成安装,而在Win下需要修改php.ini, 同样的使PHP4支持SQLite.
此时你已经无需再安装任何东西了, 而你也已经完全支持SQLite了, 一个简单, 快速, 可靠的数据库.
如果你需要一个管理软件, 那么你可以尝试使用SQLiteManager (www.sqlitemanager.org), 一个与PHPMyAdmin类似的针对SQLite的数据库管理系统.
该系统的界面大致如下:
2. 第一个使用SQLite的PHP程序.
我们创建一个叫binzy的数据库, 并创建一个叫Binzy的Table, 有2个字段, 分别是ID, Title. 而其中ID为INTEGER PRIMARY KEY, 即自增三主键. 并在其中插入了2条数据”Binzy”, “Jasmin”.
打开并显示数据:
if ($db = sqlite_open('../binzy.db', 0666, $sqliteerror)) { // 打开 SQLite$result = sqlite_query($db,'select * from Binzy'); // 查询while($row = sqlite_fetch_array($result)) // 获得结果 { print 'ID=>'.$row['MyID'].', Name=>'.$row['Name'].'<br />'; } } else {die ($sqliteerror);} |
结果如下,
接下来Insert一条记录, 其中我们会使用到SQLite的事务.
if ($db = sqlite_open('../binzy.db', 0666, $sqliteerror)) {
sqlite_query($db,'BEGIN TRANSACTION'); // 开始事务 if (@sqlite_query($db,'insert into Binzy (Name) values (/'Binzy&Jasmin/')')) { print 'Execute Successfully'; sqlite_query($db,'COMMIT TRANSACTION'); // 提交事务 } else { print sqlite_error_string(sqlite_last_error($db)); sqlite_query($db,'ROLLBACK TRANSACTION'); // 回滚事务 } } else { die ($sqliteerror); } |
如果执行失败, 便会出现这样的画面,
成功则是这样的,
是的, 如果你已经熟悉使用PHP对MySQL之类的数据库进行操作, 那么SQLite几乎是一样的, 而且更为简洁.
3. 使用Pear::DB (PHP4中)
上面的例子中我们是使用PHP的函数直接对SQLite进行访问, 这样的访问方式是不推荐使用的. 更好的方式是使用某种数据访问抽象层, 如Pear的DB. 下面是2中查询例子的重写. 使用某个数据访问抽象层会更方便更安全, 并且可以在需要进行数据库迁移的时候尽可能减小成本.
require_once('DB.php'); $dbh = DB::connect('sqlite://@localhost/../binzy.db?mode=0666'); // 打开 $dbh->setFetchMode(DB_FETCHMODE_ASSOC); if (!DB::isError($dbh)) { $result = $dbh->query('select * from Binzy'); // 查询 if (!DB::isError($result)) { while($row = $result->fetchRow()) // 读取 { print 'ID=>'.$row['MyID'].', Name=>'.$row['Name'].'<br />'; } $dbh->disconnect(); } else { print($dbh->message); $dbh->disconnect(); } } else { print($dbh->message); $dbh->disconnect(); } |
4. 使用Creole (PHP5中)
Creole是由phpdb.org开发的面向PHP5的数据访问抽象层. 关于Creole可参考本期中的《Creole :新兴数据抽象层》.
Pear::DB并没有针对PHP5进行改变, 只是因为PHP5对PHP4良好的兼容性, 使得Pear::DB在PHP5下仍能很好的工作. 所以在你使用PHP5的时候推荐使用Creole.
require_once('creole/Creole.php'); $Connection = null; try{ $Connection = Creole::getConnection('sqlite://@localhost/../binzy.db?mode=0644'); // 获得Connection $rs = $Connection->executeQuery('select * from Binzy'); // Get ResultSet while($rs->next()) { print 'ID=>'.$rs->getInt('myid').', Name=>'.$rs->getString('name').'<br />'; } $Connection->close(); } catch(SQLException $exception) // Catch Exception { $Connection->close(); print $exception->getMessage(); } |
(六) 总结
随着PHP5的即将到来, 给我们带来了许多新的语言特性, 使PHP更加适合于构建强大健壮的各类系统. 而随着PHP5一起走进PHP开发人员视线的SQLite则给我们带来了有别于MySQL的惊喜. 是的, 他简单却又强大, 稳定. 而在刚刚过去的六月底新版本的SQLite3已经Release了第一个测试版本, 不仅仅带来了新的文件结构, 也带来了许多新的特性.