大佬教程收集整理的这篇文章主要介绍了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 将会失败,并返回@R_210_5607@FulL 错
误代码。
--------------------------------------------------------------------------------
(2)sqlite 支持何种数据类型?
参见 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)多个应用程序或一个应用程序的多个实例可以同时访问同一个@R_607_9345@吗?
多个进程可同时打开同一个数据库。多个进程可以同时进行SELECT 操作,但在任一时刻,只能
有一个进程对数据库进行更改。
sqlite 使用读、写锁控制对数据库的访问。(在Win95/98/ME 等不支持读、 写锁的系统下,使
用一个概率性的模拟来代替。)但使用时要注意: 如果@R_607_9345@存放于一个NFS 文件系统上,
这种锁机制可能不能正常工作。 这是因为 fcntl() 文件锁在很多NFS 上没有正确的实现。 在
可能有多个进程同时访问数据库的时候,应该避免将@R_607_9345@放到NFS 上。在windows 上,
@H_456_2@microsoft 的文档中说:如果使用 FAT 文件系统而没有运行 share.exe 守护进程,那么锁可能
是不能正常使用的。那些在windows 上有很多经验的人告诉我:对于网络文件,文件锁的实现
有好多BUG,是靠不住的。如果他们说的是对的, 那么在两台或多台windows 机器间共享数据
库可能会引起不期望的问题。
我们意识到,没有其它嵌入式的 sql 数据库引擎能象 sqlite 这样处理如此多的并发。sqlite
允许多个进程同时打开一个数据库, 同时读一个数据库。当有任何进程想要写时,它必须在更
新过程中锁住@R_607_9345@。 但那通常只是几毫秒的时间。其它进程只需等待写进程干完活结束。
典型地,其它嵌入式的sql 数据库引擎同时只允许一个进程连接到数据库。
但是,ClIEnt/Server 数据库引擎(如 POSTGResql,MysqL,或 Oracle) 通常支持更高级别的
并发,并且允许多个进程同时写同一个数据库。 这种机制在ClIEnt/Server 结构的数据库上是
可能的, 因为总是有一个单一的服务器进程很好地控制、协调对数据库的访问。 如果你的应用
程序需要很多的并发,那么你应该考虑使用一个ClIEnt/Server 结构的数据库。但经验表明,
很多应用程序需要的并发,往往比其设计者所想象的少得多。
当sqlite 试图访问一个被其它进程锁住的文件时,缺省的行为是返回 @R_210_5607@BUSY。 可以在C
代码中使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函数调整这一行为。
--------------------------------------------------------------------------------
(6)sqlite 线程安全吗?
线程是魔鬼(Threads are evil)。 避免使用它们。
sqlite 是线程安全的。由于很多用户会忽略我们在上一段中给出的建议, 我们做出了这种让步。
但是,为了达到线程安全,sqlite 在编译时必须将 @R_210_5607@THREADSAFE 预处理宏置为1。在
windows 和linux 上,已编译的好的二进制发行版中都是这样设置的。 如果不确定你所使用的
库是否是线程安全的,可以调用 sqlite3_threadsafe() 接口找出。
在 3.3.1 版本之前,一个 sqlite3 结构只能被用于调用 sqlite3_open 创建的同一线程。你不
能在一个线程中打开数据库, 然后将数据库句柄传递给另外一个进程使用。 这主要是由于在好
多通用的线程实现(如RedHat9)中的限制引起的(是BUG 吗?)。 特别的,在有问题的系统
上,一个进程创建的 fcntl() 锁无法被其它线程清除或修改。所以,由于 sqlite 大量使用
fcntl() 锁做并发控制, 如果你在不同的线程间移动数据库连接,就可能会出现严重的问题。
在3.3.1 版本上,关于在线程间移动数据库连接的限制变得宽松了。在它及以后的版本中,只
要连接没有持有 fcntl() 锁,在线程间移动句柄是安全的。如果没有未决的事务,并且所有的
语句都已执行完毕, 你就可以安全的假定不再持有任何锁。
在UNIX 中,在执行 fork() 系统调用时不应携带已打开的数据库进入子进程。 那样做将会有问
题。
--------------------------------------------------------------------------------
(7)在sqlite 数据库中如何列出所有的表和索引?
如果你运行 sqlite3 命令行来访问你的数据库,可以键入 “.tables”来获得所有表的列表。
或者,你可以输入 “.scheR_39_11845@a” 来看整个数据库模式,包括所有的表的索引。输入这些命令,
后面跟一个liKE 模式匹配可以限制显示的表。
在一个 C/C++ 程序中(或者脚本语言使用 Tcl/Ruby/Perl/Python 等) 你可以在一个特殊的名
叫 sqlite_master 上执行一个SELECT 查询以获得所有 表的索引。每一个 sqlite 数据库都有
一个叫 sqlite_master 的表, 它定义数据库的模式。 sqlite_master 表看起来如下:
type TEXT,
@R_8_@R_696_10018@@T,
sql TEXT
对于表来说,type 字段永远是 'table',name 字段永远是表的名字。所以,要获得数据库中所
有表的列表, 使用下列SELECT 语句:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
对于索引,type 等于 'index',name 则是索引的名字,tbl_name 是该索引所属的表的名字。 不
管是表还是索引,sql 字段是原先用 create table 或 CREATE INDEX 语句创建它们时的命令文
本。对于自动创建的索引(用来实现 PRIMary KEY 或 UNIQUE 约束),sql 字段为NulL。
sqlite_master 表是只读的。不能对它使用 updatE、INSERT 或 deletE。 它会被 create table、
CREATE INDEX、drop table 和 DROP INDEX 命令自动更新。
临时表不会出现在 sqlite_master 表中。临时表及其索引和触发器存放在另外一个叫
@R_210_5607@TEMP_MASTER 的表中。@R_210_5607@TEMP_MASTER 跟 sqlite_master 差不多, 但它只是对于
创建那些临时表的应用可见。如果要获得所有表的列表, 不管是永久的还是临时的,可以使用
类似下面的命令:
SELECT name FROM
(SELECT * FROM sqlite_master union all
SELECT * FROM @R_210_5607@temp_master)
WHERE type='table'
ORDER BY name
--------------------------------------------------------------------------------
(8) sqlite 数据库有已知的大小限制吗?
对有关sqlite 限制的详细讨论,见 limits.HTML 。
--------------------------------------------------------------------------------
(9) 在sqlite 中,VARCHAR 字段最长是多少?
sqlite 不强制 VARCHAR 的长度。你可以在 sqlitE 中声明一个 VARCHAR(10),sqlite 还是可
以很高兴地允许你放入500 个字符。 并且这500 个字符是原封不动的,它永远不会被截断。
--------------------------------------------------------------------------------
(10) sqlite 支持二进制大对象吗?
sqlite 3.0 及以后版本允许你在任何列中存储 BLOB 数据。 即使该列被声明为其它类型也可以。
--------------------------------------------------------------------------------
(11) 在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;
--------------------------------------------------------------------------------
(12) 我在数据库中删除了很多数据,但数据库文件没有变小,是BUG 吗?
不是。当你从sqlite 数据库中删除数据时, 未用的磁盘空间将会加入一个内部的“自由列表”
中。 当你下次插入数据时,这部分空间可以重用。磁盘空间不会丢失, 但也不会返还给操作系
统。
如果删除了大量数据,而又想缩小@R_607_9345@占用的空间,执行 VACUUM 命令。 VACUUM 将会从
头重新组织数据库。这将会使用数据库有一个空的“自由链表”, @R_607_9345@也会最小。但要
注意的是,VACUUM 的执行会需要一些时间 (在sqlite 开发时,在linux 上,大约每@H_471_5@m 字节需
要半秒种),并且, 执行过程中需要原@R_607_9345@至多两倍的临时磁盘空间。
对于 sqlite 3.1 版本,一个 auto-vacumm 模式可以替代 VACUUM 命令。 可以使用 auto_VACUUM
pragma 打开。
--------------------------------------------------------------------------------
(13) 我可以在商业产品中使用sqlite 而不需支付许可费用吗?
是的。sqlite 在 @R_772_1815@。 对代码的任何部分没有任何所有权声明。你可以使用它做任
何事。
--------------------------------------------------------------------------------
(14) 如何在字符串中使用单引号(')?
sql 标准规定,在字符串中,单引号需要使用逃逸字符,即在一行中使用两个单引号。在这方面
sql 用起来类似 Pascal 语言。 sqlite 尊循标准。如:
INSERT INTO xyz VALUES('5 O''clock');
--------------------------------------------------------------------------------
(15) @R_210_5607@scheR_39_11845@A error 是什么错误?为什么会出现该错误?
当一个准备好的(prepared)sql 语句不再有效或者无法执行时, 将返回一个 @R_210_5607@scheR_39_11845@A 错
误。发生该错误时,sql 语句必须使用 sqlite3_prepare() API 来重新编译. 在 sqlite 3 中,一
个 @R_210_5607@scheR_39_11845@A 错误只会发生在用
sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 执行 sql 时。而不会发生在使
用 sqlite3_exec()时。 在版本2 中不是这样。
准备好的语句失效的最通常原因是:在语句准备好后, 数据库的模式又被修改了。另外的原因
会发生在:
数据库离线:DETACHed.
数据库被 VACUUMed
一个用户存储过程定义被删除或改变。
一个 collation 序列定义被删除或改变。
认证函数被改变。
在所有情况下,解决方法是重新编译并执行该sql 语句。 因为一个已准备好的语句可以由于其
它进程改变数据库模式而失效, 所有使用
sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 的代码都应准备处理
@R_210_5607@scheR_39_11845@A 错误。下面给出一个例子:
int rc;
sqlite3_stmt *pStmt;
do {
/* Compile the statement from sql. Assume success. */
sqlite3_prepare(pDb,zSQL,-1,&pStmt,0);
while( @R_210_5607@ROW==sqlite3_step(pStmt) ){
/* Do something with the row of available data */
}
/* Finalize the statement. If an @R_210_5607@scheR_39_11845@A error has
** occured,then the above call to sqlite3_step() will have
** returned @R_210_5607@ERROR. sqlite3_finalize() will return
** @R_210_5607@scheR_39_11845@A. In this case the loop will execute again.
*/
} while( rc==@R_210_5607@scheR_39_11845@a );
--------------------------------------------------------------------------------
(16) 为什么 round(9.95,1) 返回 9.9 而不是 10.0? 9.95 不应该圆整 (四舍五入)吗?
sqlite 使用二进制算术,在二进制中, 无法用有限的二进制位数表示 9.95 。使用 64-bit IEEE
浮点 (sqlite 就是使用这个)最接近 9.95 的二进制表示是
9.949999999999999289457264239899814128875732421875。所在,当你输入 9.95 时,sqlite
实际上以为是上面的数字, 在四舍五入时会舍去。
这种问题在使用二进制浮点数的任何时候都会出现。 通常的规则是记住很多有限的十进制小数
都没有一个对应的二进制表示。 所以,它们只能使用最接近的二进制数。它们通常非常接近, 但
也会有些微小的不同,有些时候也会导致你所期望的不同的结果。
sqlite 是一款轻型的数据库,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使
用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K 的内存就够了。它能够支持
windows/linux/Unix 等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、php、
Java 等,还有ODBC 接口,同样比起@H_471_5@mysqL、POSTGResql 这两款开源世界著名的数据库管理系统
来讲,它的处理速度比他们都快。
sqlite 虽然很小巧,但是支持的sql 语句不会逊色于其他开源数据库,它支持的sql 包括:
ATTACH DATABASE
BEGIN transaCTION
comment
COMMIT transaCTION
copY
CREATE INDEX
CREATE trigGER
DETACH DATABASE
DROP INDEX
DROP trigGER
DROP VIEW
END transaCTION
EXPLAIN
Expression
INSERT
ON CONFliCT clause
PRAGMA
@R_772_9363@CE
SELECT
同时它还支持事务处理功能等等。也有人说它象@H_471_5@microsoft 的Access,有时候真的觉得有点象,
但是事实上它们区别很大。比如sqlite 支持跨平台,操作简单,能够使用很多语言直接创建数
据库,而不象Access 一样需要Office 的支持。如果你是个很小型的应用,或者你想做嵌入式开
发,没有合适的数据库系统,那么现在你可以考虑使用sqlite。目前它的最新版本是 3.2.2,
它的官方网站是:http://www.sqlite.org,能在上面获得源代码和文档。同时因为数据库结构
简单,系统源代码也不是很多,也适合想研究数据库系统开发的专业人士
以上是大佬教程为你收集整理的SQLite使用问题解答全部内容,希望文章能够帮你解决SQLite使用问题解答所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。