站长资源网络编程

php SQLite学习笔记与常见问题分析第1/2页

整理:jimmy2024/10/30浏览2
简介直到学会! 学之前找资料 SQLite的sql ATTACH DATABASE BEGIN TRANSACTION comment COMMIT TRANSACTION COPY CREATE INDEX CREATE TABLE CREATE TRIGGER CREATE VIEW DELETE
直到学会! 学之前找资料
SQLite的sql
ATTACH DATABASE
BEGIN TRANSACTION
comment
COMMIT TRANSACTION
COPY
CREATE INDEX
CREATE TABLE
CREATE TRIGGER
CREATE VIEW
DELETE
DETACH DATABASE
DROP INDEX
DROP TABLE
DROP TRIGGER
DROP VIEW
END TRANSACTION
EXPLAIN
expression
INSERT
ON CONFLICT clause
PRAGMA
REPLACE
ROLLBACK TRANSACTION
SELECT
UPDATE


sqlite常见问题
 (1) 如何建立自动增长字段?

简短回答:声明为 INTEGER PRIMARY KEY 的列将会自动增长。

长一点的答案: 如果你声明表的一列为 INTEGER PRIMARY KEY,那么, 每当你在该列上插入一NULL值时, NULL自动被转换为一个比该列中最大值大1的一个整数,如果表是空的, 将会是1。 (如果是最大可能的主键 9223372036854775807,那个,将键值将是随机未使用的数。) 如,有下列表:

CREATE TABLE t1(
  a INTEGER PRIMARY KEY,
  b INTEGER
);

在该表上,下列语句

INSERT INTO t1 VALUES(NULL,123);

在逻辑上等价于:

INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);

有一个新的API叫做 sqlite3_last_insert_rowid(), 它将返回最近插入的整数值。

注意该整数会比表中该列上的插入之前的最大值大1。该键值在当前的表中是唯一的。但有可能与已从表中删除的值重叠。要想建立在整个表的生命周期中唯一的键值,需要在 INTEGER PRIMARY KEY 上增加AUTOINCREMENT声明。那么,新的键值将会比该表中曾能存在过的最大值大1。如果最大可能的整数值在数据表中曾经存在过,INSERT将会失败, 并返回SQLITE_FULL错误代码。


--------------------------------------------------------------------------------

(2)SQLite3支持何种数据类型?

NULL
INTEGER
REAL
TEXT
BLOB
但实际上,sqlite3也接受如下的数据类型:
smallint  16 位元的整数。
interger  32 位元的整数。
decimal(p,s)  p 精确值和 s 大小的十进位整数,精确值p是指全部有几个数(digits)大小值    ,s是指小数点後有几位数。如果没有特别指定,则系统会设为 p=5; s=0 。
float   32位元的实数。
double   64位元的实数。
char(n)   n 长度的字串,n不能超过 254。
varchar(n)  长度不固定且其最大长度为 n 的字串,n不能超过 4000。
graphic(n)  和 char(n) 一样,不过其单位是两个字元 double-bytes, n不能超过127。   这个形态是为了支援两个字元长度的字体,例如中文字。
vargraphic(n)  可变长度且其最大长度为 n 的双字元字串,n不能超过 2000。
date   包含了 年份、月份、日期。
time   包含了 小时、分钟、秒。
timestamp  包含了 年、月、日、时、分、秒、千分之一秒。

参见 http://www.sqlite.org/datatype3.html.
--------------------------------------------------------------------------------

(3)SQLite允许向一个integer型字段中插入字符串!

这是一个特性,而不是一个bug。SQLite不强制数据类型约束。任何数据都可以插入任何列。你可以向一个整型列中插入任意长度的字符串,向布尔型列中插入浮点数,或者向字符型列中插入日期型值。 在 CREATE TABLE 中所指定的数据类型不会限制在该列中插入任何数据。任何列均可接受任意长度的字符串(只有一种情况除外: 标志为INTEGER PRIMARY KEY的列只能存储64位整数,当向这种列中插数据除整数以外的数据时,将会产生错误。

但SQLite确实使用声明的列类型来指示你所期望的格式。所以,例如你向一个整型列中插入字符串时,SQLite会试图将该字符串转换成一个整数。如果可以转换,它将插入该整数;否则,将插入字符串。这种特性有时被称为 类型或列亲和性(type or column affinity).


--------------------------------------------------------------------------------

(4)为什么SQLite不允许在同一个表不同的两行上使用0和0.0作主键?

主键必须是数值类型,将主键改为TEXT型将不起作用。

每一行必须有一个唯一的主键。对于一个数值型列, SQLite认为 '0' 和 '0.0' 是相同的, 因为他们在作为整数比较时是相等的(参见上一问题)。 所以,这样值就不唯一了。


--------------------------------------------------------------------------------

(5)多个应用程序或一个应用程序的多个实例可以同时访问同一个数据库文件吗?

多个进程可同时打开同一个数据库。多个进程可以同时进行SELECT 操作,但在任一时刻,只能有一个进程对数据库进行更改。

SQLite 使用读、写锁控制对数据库的访问。(在Win95/98/ME等不支持读、写锁的系统下,使用一个概率性的模拟来代替。)但使用时要注意:如果数据库文件存放于一个NFS文件系统上,这种锁机制可能不能正常工作。 这是因为 fcntl() 文件锁在很多NFS上没有正确的实现。在可能有多个进程同时访问数据库的时候,应该避免将数据库文件放到NFS上。在Windows上,Microsoft的文档中说:如果使用 FAT 文件系统而没有运行 share.exe 守护进程,那么锁可能是不能正常使用的。那些在Windows上有很多经验的人告诉我:对于网络文件,文件锁的实现有好多Bug,是靠不住的。如果他们说的是对的,那么在两台或多台Windows机器间共享数据库可能会引起不期望的问题。

我们意识到,没有其它嵌入式的 SQL 数据库引擎能象 SQLite 这样处理如此多的并发。SQLite允许多个进程同时打开一个数据库,同时读一个数据库。当有任何进程想要写时,它必须在更新过程中锁住数据库文件。但那通常只是几毫秒的时间。其它进程只需等待写进程干完活结束。典型地,其它嵌入式的SQL数据库引擎同时只允许一个进程连接到数据库。

但是,Client/Server数据库引擎(如 PostgreSQL, MySQL, 或 Oracle)通常支持更高级别的并发,并且允许多个进程同时写同一个数据库。这种机制在Client/Server结构的数据库上是可能的,因为总是有一个单一的服务器进程很好地控制、协调对数据库的访问。如果你的应用程序需要很多的并发,那么你应该考虑使用一个Client/Server 结构的数据库。但经验表明,很多应用程序需要的并发,往往比其设计者所想象的少得多。

当SQLite试图访问一个被其它进程锁住的文件时,缺省的行为是返回 SQLITE_BUSY。 可以在C代码中使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函数调整这一行为。
---------------------------------------------------------------------------
12下一页阅读全文