解析SQLite中的常见问题与总结详解

726 查看

1、 创建数据
如果不往数据库里面添加任何的表,这个数据库等于没有建立,不会在硬盘上产生任何文件,如果数据库已经存在,则会打开这个数据库。

2、 如何通过sqlite3.dll与sqlite3.def生成sqlite3.lib文件
LIB /DEF:sqlite3.def /machine:IX86

3、 sqlite3_open打开一个数据库时,如果数据库不存在就会新生成一个数据库文件。如果接着执行其他查询语句就会失败,比如sqlite3_prepare,编程中出现明明指定了数据库而且里面也有数据,为什么查询失败了,主要是数据库名路径不对引起的。一般的做法是先检查数据库文件是否存在,如果存在就使用sqlite3_open打开数据库;否则创建一个新的数据库。

4、 如何建立自动增长字段
声明为INTEGER PRIMARY KEY的列将会自动增长。

5、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包含了年、月、日、时、分、秒、千分之一秒。

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

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

7、为什么SQLite不允许在同一个表不同的两行上使用0和0.0作主键?
主键必须是数值类型,将主键改为TEXT型将不起作用。
每一行必须有一个唯一的主键。对于一个数值型列,SQLite认为'0'和'0.0'是相同的,因为他们在作为整数比较时是相等的(参见上一问题)。所以,这样值就不唯一了。

8、多个应用程序或一个应用程序的多个实例可以同时访问同一个数据库文件吗?
 
多个进程可同时打开同一个数据库。多个进程可以同时进行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函数调整这一行为。

9、SQLite线程安全吗?
线程是魔鬼(Threads are evil)。避免使用它们。
SQLite是线程安全的。由于很多用户会忽略我们在上一段中给出的建议,我们做出了这种让步。但是,为了达到线程安全,SQLite在编译时必须将SQLITE_THREADSAFE预处理宏置为1。在Windows和Linux上,已编译的好的二进制发行版中都是这样设置的。如果不确定你所使用的库是否是线程安全的,可以调用sqlite3_threadsafe()接口找出。

10、在SQLite数据库中如何列出所有的表和索引?
如果你运行sqlite3命令行来访问你的数据库,可以键入“.tables”来获得所有表的列表。或者,你可以输入“.schema”来看整个数据库模式,包括所有的表的索引。输入这些命令,后面跟一个LIKE模式匹配可以限制显示的表。

11、SQLite数据库有已知的大小限制吗?
在Windows和Unix下,版本2.7.4的SQLite可以达到2的41次方字节(2T字节)。老版本的为2的31次方字节(2G字节)。
SQLite版本2.8限制一个记录的容量为1M。SQLite版本3.0则对单个记录容量没有限制。
表名、索引表名、视图名、触发器名和字段名没有长度限制。但SQL函数的名称(由sqlite3_create_function() API函数创建)不得超过255个字符。

12、在SQLite中,VARCHAR字段最长是多少?
SQLite不强制VARCHAR的长度。你可以在SQLITE中声明一个VARCHAR(10),SQLite还是可以很高兴地允许你放入500个字符。并且这500个字符是原封不动的,它永远不会被截断。
 
13、在SQLite中,如何在一个表上添加或删除一列?
SQLite有有限地ALTER TABLE支持。你可以使用它来在表的末尾增加一列,可更改表的名称。如果需要对表结构做更复杂的改变,则必须重新建表。重建时可以先将已存在的数据放到一个临时表中,删除原表,创建新表,然后将数据从临时表中复制回来。

如,假设有一个t1表,其中有"a", "b", "c"三列,如果要删除列c,以下过程描述如何做:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
14、在SQLite中支持分页吗?
 
SQLite分页是世界上最简单的。如果我要去11-20的Account表的数据Select * From Account Limit 9 Offset 10;
以上语句表示从Account表获取数据,跳过10行,取9行。这个特性足够让很多的web中型网站使用这个了。也可以这样写 select * from account limit10,9和上面的的效果一样。这种写法MySQL也支持。