嵌入式数据库SQLite介绍
SQLite是一个非常轻量级自包含(lightweight and self-contained)的DBMS,源代码完全开放,可用于任何用途(SQLite is in the Public Domain)。它可移植性好,很容易使用,很小,高效而且可靠。SQLite嵌入到使用它的应用程序中,它们共用相同的进程空间,而不是单独的一个进程。从外部看,它并不像一个RDBMS,但在进程内部,它却是完整的,自包含的数据库引擎。
嵌入式数据库的一大好处就是在你的程序内部不需要网络配置,也不需要管理。因为客户端和服务器在同一进程空间运行。SQLite 的数据库权限只依赖于文件系统,没有用户帐户的概念。SQLite 有数据库级锁定,没有网络服务器。它需要的内存,其它开销很小,适合用于嵌入式设备。你需要做的仅仅是把它正确的编译到你的程序。
SQLite是一个小巧方便且功能强大的嵌入式数据库,它实现了多数的SQL-92标准,包括数据库事务(Transaction),触发器(Trigger)和多数的复杂查询。它可以同时被多个进程或者线程访问,读访问可以并行进行,写访问只能单独进行。SQLite可以被为数众多的编程语言绑定使用并且支持多个系统平台,SQLite的官方网站称,SQLite是目前使用最广泛的数据库系统,SQLite有1.25亿份随Firefox发放、2千万份随Mac机发放、2千万随内建SQLite的PHP发放、3亿份随Skype发放、1千万份随AOL邮件客户端发放、2千万份随Symbian发放、1千万份随Solaris 10发放、还有数百万份的SQLite随McAfee、iPhones和众多手机厂商发放。由此看来SQLite在已经被广泛的应用。
SQLite使用起来非常方便,仅仅需要敲入带有SQLite数据库名字的”sqlite3“命令即可。如果文件不存在,则创建一个新的(数据库)文件。然后sqlite3程序将提示你输入SQL。敲入SQL语句(以分号“;”结束),敲回车键之后,SQL语句就会执行。
SQLite特性:
- 事务是原子的,一致的,独立的,持久的(ACID),即使在使系统崩溃或掉电之后。
- 零配置——无需安装或管理。
- 实现了SQL92标准的绝大部分。(未能支持的特性)
- 将一个完整的数据库存储在一个单一的跨平台磁盘文件上。
- 支持TB级的数据库和GB级的字符串和二进制大对象。(请见limits.html)
- 代码轻巧:完全配置小于350KB;省略部分特性,可小于200KB。
- 对大部分常见的操作,快于流行的C/S数据库引擎。
- API简单,易用。
- 用ANSI-C所写。与命令行工具相结合。对其他语言的支持单独可用。
- 源代码良好注释,分支测试覆盖率达100%。
- 单一的ANSI-C形式的源代码可用,可以简单地拖放到其他项目当中。
- 自包含:没有外部依赖。
- 跨平台:直接支持Unix (Linux and Mac OS X), OS/2, 和Windows (Win32 and WinCE);可以很容易地移植到其他操作系统。
- 源代码在公共知识域中,可用于任何目的。(不过“May you do good and not evil. ”——愿你做好事,不要做坏事。)
- 附带一个独立的命令行界面客户端,可用于管理SQLite引擎。
SQLite不支持的SQL 特性
- 外键约束(FOREIGN KEY constraints)外键约束会被解析但不会被执行。
- 完整的触发器支持(Complete trigger support)现 在有一些触发器的支持,但是还不完整。 缺少的特性包括 FOR EACH STATEMENT 触发器(现在所有的触发器都必须是 FOR EACH ROW ), 在表上的 INSTEAD OF 触发器(现在 INSTEAD OF 触发器只允许在视图上), 以及递归触发器——触发自身的触发器。
- 完整的 ALTER TABLE 支持(Complete ALTER TABLE support)只支持 ALTER TABLE 命令的 RENAME TABLE 和 ADD COLUMN。 其他类型的 ALTER TABLE 操作如 DROP COLUMN,ALTER COLUMN,ADD CONSTRAINT 等等均被忽略。
- 嵌套事务(Nested transactions)现在的实现只允许单一活动事务。
- RIGHT 和 FULL OUTER JOIN(RIGHT and FULL OUTER JOIN)LEFT OUTER JOIN 已经实现,但还没有 RIGHT OUTER JOIN 和 FULL OUTER JOIN。
- 可写视图(Writing to VIEWs)SQLite 中的视图是只读的。无法在一个视图上执行 DELETE,INSERT,UPDATE。 不过你可以创建一个试图在视图上 DELETE,INSERT,UPDATE 时触发的触发器,然后在触发器中完成你所需要的工作。
- GRANT 和 REVOKE(GRANT and REVOKE)由 于 SQLite 读和写的是一个普通的磁盘文件, 因此唯一可以获取的权限就是操作系统的标准的文件访问权限。 一般在客户机/服务器架构的关系型数据库系统上能找到的 GRANT 和 REVOKE 命令对于一个嵌入式的数据库引擎来说是没有意义的, 因此也就没有去实现。
SQLite不支持的SQL语法
- TOP
这是一个大家经常问到的问题,例如在SQLSERVER中可以使用如下语句来取得记录集中的前十条记录:
SELECT TOP 10 * FROM [index] ORDER BY indexid DESC;
但是这条SQL语句在SQLite中是无法执行的,应该改为:
SELECT * FROM [index] ORDER BY indexid DESC limit 0,10;
其中limit 0,10表示从第0条记录开始,往后一共读取10条 - 创建视图(Create View)
SQLite在创建多表视图的时候有一个BUG,问题如下:
CREATE VIEW watch_single AS SELECT DISTINCT watch_item.[watchid],watch_item.[itemid] FROM watch_item;
上面这条SQL语句执行后会显示成功,但是实际上除了SELECT COUNT(*) FROM [watch_single ] WHERE watch_ single.watchid = 1;能执行之外是无法执行其他任何语句的。其原因在于建立视图的时候指定了字段所在的表名,而SQLite并不能正确地识别它。所以上面的创建语句要改为:
CREATE VIEW watch_single AS SELECT DISTINCT [watchid],[itemid] FROM watch_item;
但是随之而来的问题是如果是多表的视图,且表间有重名字段的时候该怎么办? - COUNT(DISTINCT column)
SQLite在执行如下语句的时候会报错:SELECT COUNT(DISTINCT watchid) FROM [watch_item] WHERE watch_item.watchid = 1;其原因是SQLite的所有内置函数都不支持DISTINCT限定,所以如果要统计不重复的记录数的时候会出现一些麻烦。比较可行的做法是先建立一个不重复的记录表的视图,然后再对该视图进行计数 - 外连接
虽然SQLite官方已经声称LEFT OUTER JOIN 已经实现,但还没有 RIGHT OUTER JOIN 和 FULL OUTER JOIN。但是实际测试表明似乎并不能够正常的工作。以下三条语句在执行的时候均会报错:SELECT tags.[tagid] FROM [tags],[tag_rss] WHERE tags.[tagid] = tag_rss.[tagid](*);
SELECT tags.[tagid] FROM [tags],[tag_rss] WHERE LEFT OUTER JOIN tag_rss.[tagid] = tags.[tagid];
SELECT tags.[tagid] FROM [tags],[tag_rss] WHERE LEFT JOIN tag_rss.[tagid] = tags.[tagid];
SQLite和SQL Server语法上的一些区别
- @@IDENTITY LAST_INSERT_ROWID()
- SELECT cn = COUNT(*) FROM … SELECT COUNT(*) cn FROM …
- LIMIT startIndex,itemCn 这儿的startIndex是从0开始的,而ROW_NUMBER()是从1开始的
- sqlite中没有SELECT TOP,用LIMIT即可
- SQLite自增字段,如果在事务中插入数据失败,并不会占用增长后的id,而sql server中对应的id将无效
- SQLite中没有GETDATE日期函数
- SQLite支持REPLACE INTO语法,sql server 2008中支持merge to
SQLite 的数据类型:
首先你会接触到一个让你惊讶的名词: Typelessness(无类型). 对! SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 无论这列声明的数据类型是什么(只有在一种情况下不是, 稍后解释). 对于SQLite来说对字段不指定类型是完全有效的. 如:
Create Table ex1(a, b, c);
诚然SQLite允许忽略数据类型, 但是仍然建议在你的Create Table语句中指定数据类型. 因为数据类型对于你和其他的程序员交流, 或者你准备换掉你的数据库引擎.
SQLite In PHP:
PHP5开始已经默认支持SQLite了,PHP4需要进行安装。
SQLite建议应用场合:
- 作为应用文件格式。在应用中使用SQLite,而不是使用fopen()来生成XML文件或某些专有格式的文件来存储数据。这样你将避免额外写一个问题重重的分析器,你的数据将变得更加容易访问,更加跨平台,更新操作将具备事务性。
- 作为小电子器件的数据库。SQLite是手机、PDA、MP3、机顶盒以其其他小电子器件常用的数据库引擎。SQLite代码轻巧,能充分利用内存空间、磁盘空间以及带宽;高度可靠,并且无需数据库管理的维护。
- 作为网站数据库。因为它无需配置,将信息存储在磁盘文件上,SQLite是支撑中小型网站数据存储受欢迎的选择。
- 企业RDBMS的代用品。SQLite常被用作用于演示与测试目的的企业RDBMS的借用品。SQLite速度快,无需配置,使得它为测试省去很多事,也很容易搭建演示系统。
不能胜任的地方:
- C/S结构的应用:如果你的应用程序要通过网络访问后端的数据库,应该考虑使用支持C/S结构的数据库,而不是SQLite. SQLite当中的文件锁并不能保持多客户端同时访问数据库的同一部分导致对文件的损坏。
- 大型网站:缺省页大小是1KB,一个SQLite数据库的大小限制是2TB,即使它能处理更大的数据库,SQLite仍然是只为一个数据库创建一个磁盘文件,很多文件系统本身的限制,使其大小要小于2TB。所以,它不能支持大型网站的数据库存储。
- 高并发:SQLite使用读/写来锁定整个数据库文件。如果有一个进程正在读取数据库的任何一部分,就会阻止其它进程去写数据库的任何其它部分。类似,如果有一进程正在写操作,其它所有进程就不能读其它任何部分。在多数情况下,这并不是问题。每个应用都会很快完成数据库操作,锁定的时间也不会太长。但是有些应用需要更高的并发能力,这时必须选择其它数据库来达到高并发。
参考资料:
http://cn.php.net/manual/zh/book.sqlite.php
http://jianlee.ylinux.org/Computer/Server/sqlite.html
http://blog.sina.com.cn/s/blog_502c8cc40100pppf.html
http://www.linux-ren.org/forum.php?mod=viewthread&tid=64085&fromuid=36714