本文主要介绍SQLite3在使用中的一些常见问题,具体如何在代码中调用 请看此文。
什么是SQLite?
SQLite(www.sqlite.org)是一个嵌入式的数据库管理系统,符合大部分的SQL 92标准,它本身仅仅是一个数百KB的动态链接库。它使用一个文件作为存放全部数据的场所。在应用程序中使用的话不需要任何的配置,十分方便。
何时使用?
SQLite的优点是零配置,对程序所在的计算机没有任何要求——只要有一个dll就可以,因此它尤其适合于作为个人应用程序的数据库,放在托管服务器上的访问流量不十分巨大的网站的数据库,据SQLite官网的说明,对于日点击量小于10万的网站,都是合适的——日点击率超过10万的网站是不多的。
SQLite不提供表级别的锁定,一旦有某个进程有写操作或者启用了事物,就会锁住整个数据库,从而挂起其它进程,因此它不适合于高并发的场合,也不适合C/S程序。
如何使用?
SQLite本身提供了一套C/C++API的说明,另外,还有一个命令行工具。不过,使用都不很方便。要直接操作SQLite数据库,可以使用一个叫做SQLiteExpert的工具,它的Personal版本是可以免费得到的。要在.NET程序中使用SQLite,当然要一个ADO.NET的驱动,这个驱动很容易获得,而且不止一个版本,比较常用的是SQLite.NET,它集成了ADO.NET驱动和VS.NET的设计器支持。
安装了SQLite.NET之后,在VS的Server面板中添加数据库连接,就会有Sqlite的选项:
如果在页面上配置了SqlDataSource,会在webConfig中自动生成一个连接字符串:
<connectionStrings>
<add name="SQLite3" connectionString="data source=E:\ProjectMy\net\ShopAds\App_Data\shop.db3;cache size=4000"
providerName="System.Data.SQLite" />
</connectionStrings>
SQLite的连接字符串很简单,只有一个属性是必填的,那就是data source,data source后面跟上数据库文件的路径就可以,但是如果在托管服务器上,我们无权知道文件所在的绝对路径。可以使用ADO.NET提供的另一种写法:
<add name="SQLite3" connectionString="data source=|DataDirectory|shop.db3"
providerName="System.Data.SQLite" />
其中 |DataDirectory|表示网站的App_Data目录。这个方法不仅适合于Sqlite3,对于需要加载文件的数据库,例如Access或者通过SqlExpress附加的SQL Server数据库文件都是适用的。
不同点
(1)数据类型
SQLite与其他常见的DBMS的最大不同是它对数据类型的支持。其他常见的DBMS通常支持强类型的数据,也就是每一列的类型都必须预先指定,但是SQLite采用的是弱类型的字段。实际上,其内部仅有下列五种存储类型:
NULL: 表示一个NULL值
INTEGER: 用来存储一个整数,根据大小可以使用1,2,3,4,6,8位来存储.
REAL: IEEE 浮点数
TEXT: 按照字符串来存储
BLOB: 按照二进制值存储,不做任何改变.
要注意,这些类型是值本身的属性,而不是列的属性.
但是为了和其他DBMS(以及SQL标准)兼容,在其create table语句中可以指定列的类型,为此,SQLite有个列相似性的概念(Column Affinity). 列相似性是列的属性,SQLite有以下几种列相似性:
TEXT: TEXT列使用NULL,TEXT或者BLOB存储任何插入到此列的数据,如果数据是数字,则转换为TEXT.
NUMERIC: NUMERIC列可以使用任何存储类型,它首先试图将插入的数据转换为REAL或INTEGER型的,如果成功则存储为REAL和INTEGER型,否则不加改变的存入.
INTEGER:和NUMERIC类似,只是它将可以转换为INTEGER值都转换为INTEGER,如果是REAL型,且没有小数部分,也转为INTEGER
REAL: 和NUMERIC类型 只是它将可以转换为REAL和INTEGER值都转换为REAL.
NONE:不做任何改变的尝试.
SQLite根据create table语句来决定每个列的列相似性.规则如下(大小写均忽略):
1. 如果数据类型中包括INT,则是INTEGER
2. 如果数据类型中包括CHAR,CLOB,TEXT则是TEXT
3. 如果数据类型中包括BLOB,或者没有指定数据类型,则是NONE
4. 如果数据类型中包括REAL,FLOA或者DOUB,则是REAL
5. 其余的情况都是NUMERIC
由上可知,对于sqlite来说 char,varchar,nchar,nvarchar等都是等价的,且后面最大长度也是没有意义的。但是对于其他DBMS却不是相同的。另外,列相似性仅仅是向Sqlite提出了一个存储数据的建议,即使实际存储的数据类型和列相似性不一致,SQLite还是可以成功插入的,下面给出一个例子来说明下以上论述,注意,这个例子需要在SQLite的命令行下运行,如果在SQLite Expert工具下执行,SQLite会进行一些额外的处理。
如下图,创建一个新表,两列的类型分别是int 和varchar,但是还是可以插入其他类型的数据,并且可以正确读出。
要注意SQLite的这种特性可能会给SQLite的ADO驱动造成一些麻烦,因为.NET都是强类型的语言,必须把数据库中的字段转换为合适的类型,所以在插入数据的时候,还是应该严格的按照create table中的定义插入数据。
(2)自增列
在SQL Server中,只需要指定identity(1,1)就可以设定自增列,但是在SQLite中不支持这样做。在SQLite中,任何一张表都有一个字段类型是Integer,且是自增的,这个列是作为B树的索引的,它的名字是ROWID,如下图所示:
test2表虽然只有一列,但是ROWID列还是存在的。在程序中对任何一张表都可以使用ROWID作为自增列。不过这样可能导致和其他数据库的不兼容,SQLite中如果一个列的声明类型是Integer,并且是主键,那么这个列的名字就成为ROWID的别名。注意,声明类型必须是Integer,而不能是int或bigint之类。例如:
注意上面例子的最后3条语句,它显示了SQLite默认的自增列算法是在当前表中最大的数再加1,这样可能导致的结果是ID被重复使用——当最后一条数据被删除的时候。这与SQL Server的Identity列的行为是不一致的,例如:
SQL Server会记住每一次插入的序号,哪怕它已经被删除了。要实现SQL Server 这样的效果,需要使用autoincrement关键字。如下例所示:
不过 autoincrement关键字不被SQL Server支持(我不知道SQL 92标准中是否有此关键字),同样SQL Server的 indentity关键字在SQLite中也无法使用,因为SQLite只要求声明类型必须是integer才可以启用自增列。所以,我想不出什么方法能使建库的脚本能够不加修改的被两种数据库使用。
(3) 日期函数
Sqlite的日期函数比较有特色,它的使用本质上是调用C的库函数strftime,基本使用方法如下:
(4) 不被支持的特性
用户自定义函数,存储过程
外键的约束(不过可以通过自定义触发器来替代)
right out join , full out join
grant revoke