SQLite常见问题解答教程_第1页
SQLite常见问题解答教程_第2页
SQLite常见问题解答教程_第3页
SQLite常见问题解答教程_第4页
SQLite常见问题解答教程_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

SQLite常见问题解答教程SQLite特点:

不需要配置,不需要安装,也不需要管理员

支持大部分SQL92

一个完整的数据库保存在磁盘上面一个文件

同一个数据库文件可以在不同机器上面使用

最大支持数据库到2T

字符和BLOB的支持仅限制于可用内存

整个系统少于3万行代码,少于250KB的内存占用(gcc)

大部分应用比目前常见的客户端/服务端的数据库快

没有其它依赖

源代码开放,代码95%有较好的注释

简单易用的API.官方带有TCL的编译版本。其它的单独提供

php从5.x开始默认内置编译了SQLite,4.x需要通过pear来安装pearinstallsqliteSQLite常用于嵌入到程序,为一些需要数据库,但是不必要安装中/大型的数据库,而且进行的是比较普通的操作(例如select/insert/delete之类的)

php的sqlite的一些例子权所有

以下为打开一个名叫sqlite.db的库,如果不存在,会创建一个(需要目录可写)

$db_name='sqlite.db';

$db=newSQLiteDatabase($db_name,0644,$error);

if($error)exit($error);

创建一个表,三个字段

user,主键,非空,长度100的varchar

pass,非空,长度100的varchar

date,非空,整型,索引

这里使用了queryExec而不是query.因为只是执行,不需要返回结果

注意:在SQLite里面query也是可以执行多行语句,但是如果有结果返回的,则只会有执行第一个有结果返回的命令。

执行失败将会返回FALSE.

$db->queryexec("

CREATETABLEuser(

userVARCHAR(100)NOTNULLPRIMARYKEY,

passVARCHAR(100)NOTNULL,

dateINTEGERNOTNULL,

);

CREATEINDEXuser_dateONuser(date);

");

插入一条数据

$db->query("INSERTINTOuser(user,pass,date)VALUES('admin','password',123456789)");

$db->query("INSERTINTOuser(user,pass,date)VALUES('super','password2',123456790)");

对某条记录进行更新

$db->query("UPDATEuserSETpassword='password1'WHEREuser='admin'");

查询

PHP下面SQLite的查询有很多形式

sqlite_array_query进行一个查询,直接将返回的结果放入array

sqlite_query是个普通的执行命令,返回为handle

返回来的handle可以通过以下来获取结果

sqlite_fetch_all获取所有结果并且将每条结果作为array,然后放入一个大的array里面

sqlite_fetch_array获取下一个结果作为array

sqlite_fetch_column_types—Returnanarrayofcolumntypesfromaparticulartable

sqlite_fetch_object获取下一个结果返回一个对象(obj)

sqlite_fetch_single只获取第一列结果,返回为字符变量

sqlite_fetch_string等同于sqlite_fetch_single

因此会很方便写数据库的查询

例子:

$r=$db->singleQuery("SELECTpasswordFROMuserWHEREuser='admin'");

//$r则为返回来的password1字符串

$q=$db->Query("SELECT*FROMuser");

while($r=$q->fetch()){

echo"User:$r[user]Password:$r[pass]Date:$r[date]n";

}

权所有

$r=$db->fetchAll("SELECTuser,passwordFROMuser");

print_r($r);

使用SQLite最大的好处是不用依赖使用其它DB,而且基本不需要担心DBserver崩溃了你的程序就跟着挂了。

另外就是C/C++/delphi/java的可以把整个数据库引擎内嵌,不需要调用其它API,接口等。

sqlite简明教程

如何建立自动增长字段?

SQLite支持何种数据类型?

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

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

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

SQLite线程安全吗?

在SQLite数据库中如何列出所有的表和索引?

SQLite数据库有已知的大小限制吗?

在SQLite中,VARCHAR字段最长是多少?

SQLite支持二进制大对象吗?

在SQLite中,如何在一个表上添加或删除一列?

我在数据库中删除了很多数据,但数据库文件没有变小,是Bug吗?

我可以在商业产品中使用SQLite而不需支付许可费用吗?

如何在字符串中使用单引号(')?

SQLITE_SCHEMAerror是什么错误?为什么会出现该错误?

为什么ROUND(9.95,1)返回9.9而不是10.0?9.95不应该圆整(四舍五入)吗?

(1)如何建立自动增长字段?

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

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

CREATETABLEt1(

aINTEGERPRIMARYKEY,

bINTEGER

);

在该表上,下列语句

INSERTINTOt1VALUES(NULL,123);

在逻辑上等价于:

INSERTINTOt1VALUES((SELECTmax(a)FROMt1)+1,123);

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

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

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

参见/datatype3.html.

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

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

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

(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函数调整这一行为。

(6)SQLite线程安全吗?

线程是魔鬼(Threadsareevil)。避免使用它们。

SQLite是线程安全的。由于很多用户会忽略我们在上一段中给出的建议,我们做出了这种让步。但是,为了达到线程安全,SQLite在编译时必须将SQLITE_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”来获得所有表的列表。或者,你可以输入“.schema”来看整个数据库模式,包括所有的表的索引。输入这些命令,后面跟一个LIKE模式匹配可以限制显示的表。

在一个C/C++程序中(或者脚本语言使用Tcl/Ruby/Perl/Python等)你可以在一个特殊的名叫SQLITE_MASTER上执行一个SELECT查询以获得所有表的索引。每一个SQLite数据库都有一个叫SQLITE_MASTER的表,它定义数据库的模式。SQLITE_MASTER表看起来如下:

CREATETABLEsqlite_master(

typeTEXT,

nameTEXT,

tbl_nameTEXT,

rootpageINTEGER,

sqlTEXT

);

对于表来说,type字段永远是'table',name字段永远是表的名字。所以,要获得数据库中所有表的列表,使用下列SELECT语句:

SELECTnameFROMsqlite_master

WHEREtype='table'

ORDERBYname;

对于索引,type等于'index',name则是索引的名字,tbl_name是该索引所属的表的名字。不管是表还是索引,sql字段是原先用CREATETABLE或CREATEINDEX语句创建它们时的命令文本。对于自动创建的索引(用来实现PRIMARYKEY或UNIQUE约束),sql字段为NULL。

SQLITE_MASTER表是只读的。不能对它使用UPDATE、INSERT或DELETE。它会被CREATETABLE、CREATEINDEX、DROPTABLE和DROPINDEX命令自动更新。

临时表不会出现在SQLITE_MASTER表中。临时表及其索引和触发器存放在另外一个叫SQLITE_TEMP_MASTER的表中。SQLITE_TEMP_MASTER跟SQLITE_MASTER差不多,但它只是对于创建那些临时表的应用可见。如果要获得所有表的列表,不管是永久的还是临时的,可以使用类似下面的命令:

SELECTnameFROM

(SELECT*FROMsqlite_masterUNIONALL

SELECT*FROMsqlite_temp_master)

WHEREtype='table'

ORDERBYname

(8)SQLite数据库有已知的大小限制吗?

对有关SQLite限制的详细讨论,见limits.html。

(9)在SQLite中,VARCHAR字段最长是多少?

SQLite不强制VARCHAR的长度。你可以在SQLITE中声明一个VARCHAR(10),SQLite还是可以很高兴地允许你放入500个字符。并且这500个字符是原封不动的,它永远不会被截断。

(10)SQLite支持二进制大对象吗?

SQLite3.0及以后版本允许你在任何列中存储BLOB数据。即使该列被声明为其它类型也可以。

(11)在SQLite中,如何在一个表上添加或删除一列?

SQLite有有限地ALTERTABLE支持。你可以使用它来在表的末尾增加一列,可更改表的名称。如果需要对表结构做更复杂的改变,则必须重新建表。重建时可以先将已存在的数据放到一个临时表中,删除原表,创建新表,然后将数据从临时表中复制回来。

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

BEGINTRANSACTION;

CREATETEMPORARYTABLEt1_backup(a,b);

INSERTINTOt1_backupSELECTa,bFROMt1;

DROPTABLEt1;

CREATETABLEt1(a,b);

INSERTINTOt1SELECTa,bFROMt1_backup;

DROPTABLEt1_backup;

COMMIT;

(12)我在数据库中删除了很多数据,但数据库文件没有变小,是Bug吗?

不是。当你从SQLite数据库中删除数据时,未用的磁盘空间将会加入一个内部的“自由列表”中。当你下次插入数据时,这部分空间可以重用。磁盘空间不会丢失,但也不会返还给操作系统。

如果删除了大量数据,而又想缩小数据库文件占用的空间,执行VACUUM命令。VACUUM将会从头重新组织数据库。这将会使用数据库有一个空的“自由链表”,数据库文件也会最小。但要注意的是,VACUUM的执行会需要一些时间(在SQLite开发时,在Linux上,大约每M字节需要半秒种),并且,执行过程中需要原数据库文件至多两倍的临时磁盘空间。

对于SQLite3.1版本,一个auto-vacumm模式可以替代VACUUM命令。可以使用auto_vacuumpragma打开。

(13)我可以在商业产品中使用SQLite而不需支付许可费用吗?

是的。SQLite在publicdomain。对代码的任何部分没有任何所有权声明。你可以使用它做任何事。

(14)如何在字符串中使用单引号(')?

SQL标准规定,在字符串中,单引号需要使用逃逸字符,即在一行中使用两个单引号。在这方面SQL用起来类似Pascal语言。SQLite尊循标准。如:

INSERTINTOxyzVALUES('5O''clock');

(15)SQLITE_SCHEMAerror是什么错误?为什么会出现该错误?

当一个准备好的(prepared)SQL语句不再有效或者无法执行时,将返回一个SQLITE_SCHEMA错误。发生该错误时,SQL语句必须使用sqlite3_prepare()API来重新编译.在SQLite3中,一个SQLITE_SCHEMA错误只会发生在用sqlite3_prepare()/sqlite3_step()/sqlite3_finalize()API执行SQL时。而不会发生在使用sqlite3_exec()时。在版本2中不是这样。

准备好的语句失效的最通常原因是:在语句准备好后,数据库的模式又被修改了。另外的原因会发生在:

数据库离线:DETACHed.

数据库被VACUUMed

一个用户存储过程定义被删除或改变。

一个collation序列定义被删除或改变。

认证函数被改变。

在所有情况下,解决方法是重新编译并执行该SQL语句。因为一个已准备好的语句可以由于其它进程改变数据库模式而失效,所有使用sqlite3_prepare()/sqlite3_step()/sqlite3_finalize()API的代码都应准备处理SQLITE_SCHEMA错误。下面给出一个例子:

intrc;

sqlite3_stmt*pStmt;

charzSql[]="SELECT";

do{

sqlite3_prepare(pDb,zSql,-1,&pStmt,0);

while(SQLITE_ROW==sqlite3_step(pStmt)){

}

rc=sqlite3_finalize(pStmt);

}while(rc==SQLITE_SCHEMA);

(16)为什么ROUND(9.95,1)返回9.9而不是10.0?9.95不应该圆整(四舍五入)吗?

SQLite使用二进制算术,在二进制中,无法用有限的二进制位数表示9.95。使用64-bitIEEE浮点(SQLite就是使用这个)最接近9.95的二进制表示是9.949999999999999289457264239899814128875732421875。所在,当你输入9.95时,SQLite实际上以为是上面的数字,在四舍五入时会舍去。

这种问题在使用二进制浮点数的任何时候都会出现。通常的规则是记住很多有限的十进制小数都没有一个对应的二进制表示。所以,它们只能使用最接近的二进制数。它们通常非常接近,但也会有些微小的不同,有些时候也会导致你所期望的不同的结果。

SQLite是一款轻型的数据库,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。

SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库,它支持的SQL包括:

ATTACHDATABASE

BEGINTRANSACTION

comment

COMMITTRANSACTION

COPY

CREATEINDEX

CREATETABLE

CREATETRIGGER

CREATEVIEW

DELETE

DETACHDATABASE

DROPINDEX

DROPTABLE

DROPTRIGGER

DROPVIEW

ENDTRANSACTION

EXPLAIN

expression

INSERT

ONCONFLICTclause

PRAGMA

REPLACE

ROLLBACKTRANSACTION

SELECT

UPDATE

同时它还支持事务处理功能等等。也有人说它象Microsoft的Access,有时候真的觉得有点象,但是事实上它们区别很大。比如SQLite支持跨平台,操作简单,能够使用很多语言直接创建数据库,而不象Access一样需要Office的支持。如果你是个很小型的应用,或者你想做嵌入式开发,没有合适的数据库系统,那么现在你可以考虑使用SQLite。目前它的最新版本是3.2.2,它的官方网站是:,能在上面获得源代码和文档。同时因为数据库结构简单,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论