sqlite相关使用

1、SQLite简介  html

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

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

  ATTACH DATABASEgit

  BEGIN TRANSACTION程序员

  commentsql

  COMMIT TRANSACTION数据库

  COPYexpress

  CREATE INDEX编程

  CREATE TABLEwindows

  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

  同时它还支持事务处理功能等等。也有人说它象Microsoft的Access,有时候真的以为有点象,可是事实上它们区别很大。好比SQLite 支持跨平台,操做简单,可以使用不少语言直接建立数据库,而不象Access同样须要Office的支持。若是你是个很小型的应用,或者你想作嵌入式开发,没有合适的数据库系统,那么如今你能够考虑使用SQLite。目前它的最新版本是 3.2.2,它的官方网站是:http://www.sqlite.org或者http://www.sqlite.com.cn,能在上面得到源代码和文档。同时由于数据库结构简单,系统源代码也不是不少,也适合想研究数据库系统开发的专业人士

  下面是访问SQLite官方网站: http://www.sqlite.org/ 时第一眼看到关于SQLite的特性.

  1. ACID事务

  2. 零配置 – 无需安装和管理配置

  3. 储存在单一磁盘文件中的一个完整的数据库

  4. 数据库文件能够在不一样字节顺序的机器间自由的共享

  5. 支持数据库大小至2TB

  6. 足够小, 大体3万行C代码, 250K

  7. 比一些流行的数据库在大部分普通数据库操做要快

  8. 简单, 轻松的API

  9. 包含TCL绑定, 同时经过Wrapper支持其余语言的绑定

  10. 良好注释的源代码, 而且有着90%以上的测试覆盖率

  11. 独立: 没有额外依赖

  12. Source彻底的Open, 你能够用于任何用途, 包括出售它

  13. 支持多种开发语言,C, PHP, Perl, Java, ASP.NET,Python

  二、SQLite类型

  SQLite的数据类型

  首先你会接触到一个让你惊讶的名词: Typelessness(无类型). 对! SQLite是无类型的. 这意味着你能够保存任何类型的数据到你所想要保存的任何表的任何列中, 不管这列声明的数据类型是什么(只有在一种状况下不是, 稍后解释). 对于SQLite来讲对字段不指定类型是彻底有效的. 如:

  Create Table ex1(a, b, c);

  诚然SQLite容许忽略数据类型, 可是仍然建议在你的Create Table语句中指定数据类型. 由于数据类型对于你和其余的程序员交流, 或者你准备换掉你的数据库引擎. SQLite支持常见的数据类型, 如:

  CREATE TABLE ex2(

  a VARCHAR(10),

  b NVARCHAR(15),

  c TEXT,

  d INTEGER,

  e FLOAT,

  f BOOLEAN,

  g CLOB,

  h BLOB,

  i TIMESTAMP,

  j NUMERIC(10,5)

  k VARYING CHARACTER (24),

  l NATIONAL VARYING CHARACTER(16)

  );

  前面提到在某种状况下, SQLite的字段并非无类型的. 即在字段类型为”Integer Primary Key”时.

 

 

、SQLite的简单使用

SQLite能够到官方站点下载http://www.sqlite.org/download.html
包括:Linux,Mac OS X, Windows下的已编译文件以及源代码、帮助文档。windows版的下载地址是:http://www.sqlite.org/sqlite-3_6_23_1.zip,下载后解压就能够了。这个文件是工做在命令行下的。双击它,就直接进入命令行了。

打开以后是这样显示的:

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite>

 

1、建立数据库

按理说第一步是建立一个数据库,我是学电子的,对计算机不了解,因此我不知道mysql是如何存储数据库的。但sqlite将一个数据库存储为一个文件。咱们先进下cmd,关掉原来的sqlite3。

在命令提示符下:

sqlite3 newsql.db

而后就会自动跳到sqlite>命令提示符下。我记得在linux下用时候会在当前目录下出现newsql.db文件。但在我所用版本的windows下没有出现。而后我作了些尝试获得以下结果:

sqlite3 newsql.db

.quit

注意:.quit是在sqlite提示符下输入的,表明退出。看目录下仍是没有出现数据库文件。

sqlite3 newsql.db

;

.quit

出现了newsql.db文件。冒号加回车,在sqlite中,表明执行一条语句的意思,虽然我只输入了一个冒号加回车,没有输入任何的语句,但结果已经是不一样。

2、建立一个表

create table mytable(entry1 varchar(10),entry2 int);

不要忘了加冒号。冒号表明一条语句输入完毕。

mytable是我建立的表名。create 和table都是系统关键字。entry1,entry2是两个表项。

varchar(10) int是类型。根据我读到的内容,sqlite是不区分类型,可是咱们仍是要在建立表时,给他一个类型,以便于将这些代码移植到其余的数据库里面时更加的方便。

3、向表中插入一条记录

insert into mytable values("hello world",10);

插入完了以后才发现是否是超出定义的大小了?我定义的entry1项是varchar(10)型的,说实在的,我不知这个类型确切来说是什么意思,我猜应该是10个字符的字符串数组吧。若是那样的话我是必定超出了。但既然sqlite是不区分类型的,我想应该没有问题吧。因而我急于看看是否是这样...

4、查询表中内容

select * from mytable;

执行这条语句,会列出mytable中的全部内容。

结果为:

sqlite> select * from mytable;

hello world|10

可见仍是都插入进去了。

sqlite> insert into mytable values("goodbye cruel world",20);

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

也就是说,第一个条目的字符串彻底不受限制。

5、sqlite3 newsql.db的规则

咱们如今退出,而后从新打开数据库:

sqlite> .quit

F:/sqlite>sqlite3 newsql.db

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

可见sqlite3 newsql.db这个命令规则为:打开名为newsql.db这个数据库,若是不存在则建立一个。

6、查询一个数据库中全部的表名

sqlite数据库中有一个系统创建的表,名为sqlite_master,查询这个表能够获得全部的表。

sqlite> create table my2ndtable(theonlyentry int);

sqlite> insert into my2ndtable values(30);

sqlite> select * from sqlite_master;

table|mytable|mytable|2|CREATE TABLE mytable(entry1 varchar(10),entry2 int)

table|my2ndtable|my2ndtable|3|CREATE TABLE my2ndtable(theonlyentry int)

对于这个表的定义,官方网站的FAQ中给出以下:

CREATE TABLE sqlite_master ( type TEXT, name TEXT, tbl_name TEXT, rootpage INTEGER, sql TEXT );第一个字段类型显然会一直是table,第二个字段是名称分别是mytable和my2ndtable,见上面的结果。第三个字段表名,没弄懂是什么意,想必是所在的表的名字,可是一个表的名字和所在的表名不是同样的吗?第四个字段rootpage,我也不知指什么,这个系统的学过数据库的人应该能知道,有路过的还望告之。第五个字段是建立表的使用的sql语句吧。

7、sqlite的输出模式

 默认的输出格式是“列表”。在列表模式下,每条查询结果记录被写在一行中而且每列之间以一个字符串分割符隔开。默认的分隔符是一个管道符号(“|”)。列表符号在当你输出查询结果到另一个符号处理的程序(如AWK)中去是尤其有用。

sqlite> .mode list

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

sqlite>

这是正常的模式。

sqlite> .mode csv

sqlite> select * from mytable;

"hello world",10

"goodbye cruel world",20

变化是什么?字符串被加上了引号。

sqlite> .mode column

sqlite> select * from mytable;

hello world  10

goodbye cru  20

哎呀,第二个字符串被截断了。

.mode MODE ?TABLE?__  Set output mode where MODE is one of:

____________  csv___ Comma-separated values

____________  column_  Left-aligned columns._ (See .width)

____________  html__  HTML <table> code

____________  insert_  SQL insert statements for TABLE

____________  line__  One value per line

____________  list__  Values delimited by .separator string

____________  tabs__  Tab-separated values

____________  tcl___ TCL list elements

这些来自.help命令的输出结果。

sqlite> .mode html

sqlite> select * from mytable;

<TR><TD>hello world</TD>

<TD>10</TD>

</TR>

<TR><TD>goodbye cruel world</TD>

<TD>20</TD>

</TR>

.mode html是一种较新的输出方法。

另外,咱们也能够把输出结果输出到文件:

sqlite> .output output.txt

sqlite> select * from mytable;

sqlite> .exit



F:/sqlite>type output.txt

hello world|10

goodbye cruel world|20

8、查看数据库中全部的表

sqlite> .tables

my2ndtable  mytable

9、查看全部的表的建立语句

sqlite> .schema

CREATE TABLE my2ndtable(theonlyentry int);

CREATE TABLE mytable(entry1 varchar(10),entry2 int);

sqlite> .schema mytable

CREATE TABLE mytable(entry1 varchar(10),entry2 int);

10、数据库导出和导入

咱们能够利用这个功能作一个简单的备份,或是说建立一个一样的数据库。

第一步,把数据库倒出来:

cmd命令提示符下:

F:/sqlite>sqlite3 newsql.db ".dump" >a.sql

此语句将数据库导出成a.sql数据库语句文件,执行这个文件就能够建立一个如出一辙数据库:

F:/sqlite>sqlite3 copied.db

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

十一、删除记录
delete from mytable where entry2=10;
能够删掉mytable中全部entry2项为10的条目。
注意:不是delete * from mytable,而delete from mytable.没有*.

 

3、SQLite3 C/C++ 开发接口简介(API函数)

SQLite3SQLite一个全新的版本,它虽然是在SQLite 2.8.13的代码基础之上开发的,可是使用了和以前的版本不兼容的数据库格式和API. SQLite3是为了知足如下的需求而开发的:

  • 支持UTF-16编码.
  • 用户自定义的文本排序方法.
  • 能够对BLOBs字段创建索引.

所以为了支持这些特性我改变了数据库的格式,创建了一个与以前版本不兼容的3.0至于其余的兼容性的改变,例如全新的API等等,都将在理论介绍以后向你说明,这样可使你最快的一次性摆脱兼容性问题.

3.0版的和2.X版的API很是类似,可是有一些重要的改变须要注意全部API接口函数和数据结构的前缀都由"sqlite_"改成了"sqlite3_". 这是为了不同时使用SQLite 2.XSQLite 3.0这两个版本的时候发生连接冲突.

因为对于C语言应该用什么数据类型来存放UTF-16编码的字符串并无一致的规范所以SQLite使用了普通的void* 类型来指向UTF-16编码的字符串客户端使用过程当中能够把void*映射成适合他们的系统的任何数据类型.

SQLite 3.0一共有83API函数,此外还有一些数据结构和预约义(#defines). (完整的API介绍请参看另外一份文档.) 不过大家能够放心,这些接口使用起来不会像它的数量所暗示的那么复杂最简单的程序仍然使用三个函数就能够完成: sqlite3_open(), sqlite3_exec(),  sqlite3_close(). 要是想更好的控制数据库引擎的执行,可使用提供的sqlite3_prepare()函数把SQL语句编译成字节码,而后在使用sqlite3_step()函数来执行编译后的字节码sqlite3_column_开头的一组API函数用来获取查询结果集中的信息许多接口函数都是成对出现的,同时有UTF-8UTF-16两个版本而且提供了一组函数用来执行用户自定义的SQL函数和文本排序函数.

2.1 如何打开关闭数据库

   typedef struct sqlite3 sqlite3;
   int sqlite3_open(const char*, sqlite3**);
   int sqlite3_open16(const void*, sqlite3**);
   int sqlite3_close(sqlite3*);
   const char *sqlite3_errmsg(sqlite3*);
   const void *sqlite3_errmsg16(sqlite3*);
   int sqlite3_errcode(sqlite3*);

sqlite3_open() 函数返回一个整数错误代码,而不是像第二版中同样返回一个指向sqlite3结构体的指针. sqlite3_open()  sqlite3_open16() 的不一样之处在于sqlite3_open16() 使用UTF-16编码(使用本地主机字节顺序)传递数据库文件名若是要建立新数据库, sqlite3_open16() 将内部文本转换为UTF-16编码反之sqlite3_open() 将文本转换为UTF-8编码.

打开或者建立数据库的命令会被缓存,直到这个数据库真正被调用的时候才会被执行并且容许使用PRAGMA声明来设置如本地文本编码或默认内存页面大小等选项和参数.

sqlite3_errcode() 一般用来获取最近调用的API接口返回的错误代码. sqlite3_errmsg() 则用来获得这些错误代码所对应的文字说明这些错误信息将以 UTF-8 的编码返回,而且在下一次调用任何SQLite API函数的时候被清除. sqlite3_errmsg16()  sqlite3_errmsg() 大致上相同,除了返回的错误信息将以 UTF-16 本机字节顺序编码.

SQLite3的错误代码相比SQLite2没有任何的改变,它们分别是:

#define SQLITE_OK           0   /* Successful result */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

2.2 执行 SQL 语句

       typedef int (*sqlite_callback)(void*,int,char**, char**);
       int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);

sqlite3_exec 函数依然像它在SQLite2中同样承担着不少的工做. 该函数的第二个参数中能够编译和执行零个或多个SQL语句. 查询的结果返回给回调函数. 更多地信息能够查看API 参考.

在SQLite3里,sqlite3_exec通常是被准备SQL语句接口封装起来使用的.

       typedef struct sqlite3_stmt sqlite3_stmt;
       int sqlite3_prepare(sqlite3*, const char*, int, sqlite3_stmt**, const char**);
       int sqlite3_prepare16(sqlite3*, const void*, int, sqlite3_stmt**, const void**);
       int sqlite3_finalize(sqlite3_stmt*);
       int sqlite3_reset(sqlite3_stmt*);

sqlite3_prepare 接口把一条SQL语句编译成字节码留给后面的执行函数. 使用该接口访问数据库是当前比较好的的一种方法.

sqlite3_prepare() 处理的SQL语句应该是UTF-8编码的. 而sqlite3_prepare16() 则要求是UTF-16编码的. 输入的参数中只有第一个SQL语句会被编译. 第四个参数则用来指向输入参数中下一个须要编译的SQL语句存放的SQLite statement对象的指针, 任什么时候候若是调用 sqlite3_finalize() 将销毁一个准备好的SQL声明. 在数据库关闭以前,全部准备好的声明都必须被释放销毁. sqlite3_reset() 函数用来重置一个SQL声明的状态,使得它能够被再次执行.

SQL声明能够包含一些型如"?" 或 "?nnn" 或 ":aaa"的标记,其中"nnn" 是一个整数,"aaa" 是一个字符串. 这些标记表明一些不肯定的字符值(或者说是通配符),能够在后面用sqlite3_bind 接口来填充这些值. 每个通配符都被分配了一个编号(由它在SQL声明中的位置决定,从1开始),此外也能够用 "nnn" 来表示 "?nnn" 这种状况. 容许相同的通配符在同一个SQL声明中出现屡次, 在这种状况下全部相同的通配符都会被替换成相同的值.没有被绑定的通配符将自动取NULL值.

       int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
       int sqlite3_bind_double(sqlite3_stmt*, int, double);
       int sqlite3_bind_int(sqlite3_stmt*, int, int);
       int sqlite3_bind_int64(sqlite3_stmt*, int, long long int);
       int sqlite3_bind_null(sqlite3_stmt*, int);
       int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
       int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
       int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);

以上是 sqlite3_bind 所包含的所有接口,它们是用来给SQL声明中的通配符赋值的. 没有绑定的通配符则被认为是空值. 绑定上的值不会被sqlite3_reset()函数重置. 可是在调用了sqlite3_reset()以后全部的通配符均可以被从新赋值.

在SQL声明准备好以后(其中绑定的步骤是可选的), 须要调用如下的方法来执行:

       int sqlite3_step(sqlite3_stmt*);

若是SQL返回了一个单行结果集,sqlite3_step() 函数将返回 SQLITE_ROW , 若是SQL语句执行成功或者正常将返回 SQLITE_DONE , 不然将返回错误代码. 若是不能打开数据库文件则会返回 SQLITE_BUSY . 若是函数的返回值是 SQLITE_ROW, 那么下边的这些方法能够用来得到记录集行中的数据:

       const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
       int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
       int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
       int sqlite3_column_count(sqlite3_stmt*);
       const char *sqlite3_column_decltype(sqlite3_stmt *, int iCol);
       const void *sqlite3_column_decltype16(sqlite3_stmt *, int iCol);
       double sqlite3_column_double(sqlite3_stmt*, int iCol);
       int sqlite3_column_int(sqlite3_stmt*, int iCol);
       long long int sqlite3_column_int64(sqlite3_stmt*, int iCol);
       const char *sqlite3_column_name(sqlite3_stmt*, int iCol);
       const void *sqlite3_column_name16(sqlite3_stmt*, int iCol);
       const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
       const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
       int sqlite3_column_type(sqlite3_stmt*, int iCol);

sqlite3_column_count()函数返回结果集中包含的列数. sqlite3_column_count() 能够在执行了sqlite3_prepare()以后的任什么时候刻调用. sqlite3_data_count()除了必须要在sqlite3_step()以后调用以外,其余跟sqlite3_column_count() 大同小异. 若是调用sqlite3_step() 返回值是 SQLITE_DONE 或者一个错误代码, 则此时调用sqlite3_data_count() 将返回 0 ,然而 sqlite3_column_count() 仍然会返回结果集中包含的列数.

返回的记录集经过使用其它的几个 sqlite3_column_***() 函数来提取, 全部的这些函数都把列的编号做为第二个参数. 列编号从左到右以零起始. 请注意它和以前那些从1起始的参数的不一样.

sqlite3_column_type()函数返回第N列的值的数据类型. 具体的返回值以下:

       #define SQLITE_INTEGER  1
       #define SQLITE_FLOAT    2
       #define SQLITE_TEXT     3
       #define SQLITE_BLOB     4
       #define SQLITE_NULL     5

sqlite3_column_decltype() 则用来返回该列在 CREATE TABLE 语句中声明的类型. 它能够用在当返回类型是空字符串的时候. sqlite3_column_name() 返回第N列的字段名. sqlite3_column_bytes() 用来返回 UTF-8 编码的BLOBs列的字节数或者TEXT字符串的字节数. sqlite3_column_bytes16() 对于BLOBs列返回一样的结果,可是对于TEXT字符串则按 UTF-16 的编码来计算字节数. sqlite3_column_blob() 返回 BLOB 数据. sqlite3_column_text() 返回 UTF-8 编码的 TEXT 数据. sqlite3_column_text16() 返回 UTF-16 编码的TEXT 数据. sqlite3_column_int() 以本地主机的整数格式返回一个整数值. sqlite3_column_int64() 返回一个64位的整数. 最后, sqlite3_column_double() 返回浮点数.

不必定非要按照sqlite3_column_type()接口返回的数据类型来获取数据. 数据类型不一样时软件将自动转换.

2.3核心对象和接口

 

SQL数据库引擎的最主要任务是解析SQL语句。为了达成这个目的,开发者须要了解两个对象:

 

* 数据库链接对象:sqlite3

* 预处理语句对象:sqlite3_stmt

 

严格来说,预处理语句对象并非必须的,由于可以使用sqlite_exec或者sqlite3_get_table这些便于使用的封装接口,而这些接口封装并隐藏了预处理语句对象。尽管如此,对预处理对象的理解有助于咱们更充分的使用SQLite。

 

数据库链接对象和预处理对象是由下列的一组C/C++接口调用操纵的:

 

* sqlite3_open()

* sqlite3_prepare()

* sqlite3_step()

* sqlite3_column()

* sqlite3_finalize()

* sqlite3_close()

 

这6个C/C++接口例程和上述的两个对象构成了SQLite的核心功能。开发者对于它们的理解可以更好的使用SQLite。

 

注意,这个接口例程列表更可能是概念上的意义而不是实际的接口。许多这些接口都出如今各个版本之中。例如,上述列表中的sqlite3_open() 例程实际上有三个不一样的接口以略微不一样的方式实现相同的功能:slqite3_open(),sqlite3_open16()和sqlite3_open_v2()。列表中的实际上并不存在sqlite3_column()这个接口。显示在列表中的 “sqlite3_column()”仅仅是一个占位,表示一整套用于从表中查询出各类数据类型的列记录接口。

 

这里说明下核心接口的主要功能:

 

* sqlite3_open() 该接口打开与一个SQLite数据库文件的链接并返回一个数据库链接对象。这一般是应用程序调用的第一个SQLite API接口并且也是调用其余SQLite API接口前须要调用的接口。许多SQLite接口须要一个指向数据库链接对象的指针做为它们的第一个参数,于是这些接口也能够理解成是数据库链接对象的操做接口。该接口就是建立了这样一个数据库链接对象。

 

* sqlite3_prepare() 该接口把一个SQL语句文本转换成一个预处理语句对象并返回一个指向该对象的指针。这个接口须要一个由先前调用sqlite3_open()返回的数据库链接对象指针以及一个预处理的SQL语句文本字符串为参数。这个API并不实际解析SQL语句,仅仅是为后续的解析而对SQL语句进行的预处理。

 

注意新的应用中不建议使用sqlite3_prepare(),而应该使用另外一个接口sqlite3_prepare_v2()。

 

* sqlite3_step() 该接口用于解析一个由先前经过sqlite3_prepare()接口建立的预处理语句,直至返回第一列结果为止。经过再次调用 sqlite3_step()能够返回下一列的结果,继续不断地调用sqlite3_step()直至整个语句完成为止。对于那些并不返回结果的语句(例如:INSERT,UPDATE,DELETE语句)一次调用sqlite3_step()就完成了语句的处理。

 

* sqlite3_column() 该接口返回一个由sqlite3_step()解析的预处理语句结果集中当前行的某一列数据。每次执行sqlite3_step()都返回一个新的结果集中的一行。能够屡次调用sqlite3_column()接口返回那一行中全部列的数据。就像上面所说的那样,SQLite API中并无sqlite3_column()这样的接口。取而代之的是一组用于从结果集中查询出各个列项各类数据类型数据的函数接口。在这组函数接口中,有些接口返回结果集的大小,有些返回结果集的列数。

 

*sqlite3_column_blob()

*sqlite3_column_bytes()

*sqlite3_column_bytes16()

*sqlite3_column_count()

*sqlite3_column_double()

*sqlite3_column_int()

*sqlite3_column_int64()

*sqlite3_column_text()

*sqlite3_column_text16()

*sqlite3_column_type()

*sqlite3_column_value()

 

* sqlite3_finalize() 该接口销毁以前调用sqlite3_prepare()建立的预处理语句。每个预处理语句都必须调用这个接口进行销毁以免内存泄

漏。

* sqlite3_close() 该接口关闭一个由以前调用sqlite3_open()建立的数据库链接。全部与该链接相关的预处理语句都必须在关闭链接以前销毁。

2.4扩展SQLite

 

SQLite包含一些可用于扩展其功能的一些其余接口,这些接口包括:

 

 sqlite3_create_collation()

 sqlite3_create_function()

 sqlite3_create_module()

 

sqlite3_create_collation()接口用于为索引文本建立新的对照序列。sqlite3_create_module()接口用于注册新的续表实现接口。

 

sqlite3_create_function()接口建立新的SQL函数-便可以是单一的也能够是组合的接口。新的函数实现一般利用下列的辅助接口:

 

 sqlite3_aggregate_context()

 sqlite3_result()

 sqlite3_user_data()

 sqlite3_value()

 

SQLite中全部内建的SQL函数接口也是经过这些相同的接口实现的。查看SQLite源代码,尤为是date.cfunc.c两个文件就有许多这方面的例子。

 

4、在VC下使用SQLite

#include "../sqlite3_lib/sqlite3.h"

 

#pragma comment(lib, "../sqlite3_lib/sqlite3.lib")

 

static int _sql_callback(void * notused, int argc, char ** argv, char ** szColName)

{

    int i;

    for ( i=0; i < argc; i++ )

    {

        printf( "%s = %s/n", szColName[i], argv[i] == 0 ? "NUL" : argv[i] );

    }

      

    return 0;

}

 

int main(int argc, char * argv[])

{

    const char * sSQL1 = "create table users(userid varchar(20) PRIMARY KEY, age int, birthday datetime);";

    const char * sSQL2 = "insert into users values('wang',20,'1989-5-4');";

    const char * sSQL3 = "select * from users;";

 

    sqlite3 * db = 0;

    char * pErrMsg = 0;

    int ret = 0;

   

    // 链接数据库

    ret = sqlite3_open("./test.db", &db);

      

    if ( ret != SQLITE_OK )

    {

        fprintf(stderr, "没法打开数据库: %s", sqlite3_errmsg(db));

        return(1);

    }

      

    printf("数据库链接成功!/n");

      

    // 执行建表SQL

 

    sqlite3_exec( db, sSQL1, 0, 0, &pErrMsg );

    if ( ret != SQLITE_OK )

    {

        fprintf(stderr, "SQL error: %s/n", pErrMsg);

        sqlite3_free(pErrMsg);

    }

      

    // 执行插入记录SQL

    sqlite3_exec( db, sSQL2, 0, 0, &pErrMsg);

 

    // 查询数据表

    sqlite3_exec( db, sSQL3, _sql_callback, 0, &pErrMsg);

 

    // 关闭数据库

    sqlite3_close(db);

    db = 0;

      

    return 0;

}

 

使用事务

 
    在上面的例子中,咱们向数据库里插入了10条数据,而后再从数据库里读出来。细心的你不知道有没有发现,在执行Insert的时候
,并无使用同一个事 务。在不少状况下,咱们须要使用事务来保证对数据库操做的原子性。Sqlite是支持事务的,并且对事务的使用很是简单:
使用sql语句”begin;” 表示事务开始,”rollback;”表示事务的回滚,”commit;”表示事务的提交。下面咱们对上面例子中的代码做一下修改,
给Insert操做添 加事务支持:
 
//... ...

bool is_succed = true; sqlite3_exec(conn, "begin;", 0, 0, 0);  //

开启事务 //添加10条记录 for (int i = 0; i < 10; i++) {     // 执行SQL     sprintf(sql, "INSERT INTO [test_for_cpp] ([id], [name], [age]) /         VALUES (%d, '%s', %d)", i, "JGood", i);     if (SQLITE_OK != sqlite3_exec(conn, sql, 0, 0, &err_msg))     {         is_succed = false;         break;     } } if (is_succed)     sqlite3_exec(conn, "commit;", 0, 0, 0);  // 提交事务 else     sqlite3_exec(conn, "rollback;", 0, 0, 0);  // 回滚事务 //... ...

 

使用sql参数

 
    基本上,使用sqlite3_open, sqlite3_close, sqlite3_exec这三个函数,
能够完成大大部分的工做。但还不完善。上面的例子中,都是直接以sql语句的形式来操做数据库,这样很容易被注入。因此有必要使用sql参数。
 
sqlite3_prepare
 
sqlite3_bind_*
 
sqlite3_step
 
sqlite3_column_*
 
struct sqlite3_stmt
 
sqlite3_finalize
 
    sqlite3_prepare用来编译sql语句。sql语句被执行以前,
必须先编译成字节码。sqlite3_stmt是一个结构体,表示sql语句 编译后的字节码。sqlite3_step用来执行编译后的sql语句。
sqlite3_bind_*用于将sql参数绑定到sql语句。 sqlite3_column_*用于从查询的结果中获取数据。sqlite3_finalize用来释放sqlite3_stmt对象。代码最能说明函 数的功能,
下面就用一个例子来演示吧~~
 
// ----------------------------------------------
// http://blog.csdn.net/JGood
 
// sqlite3_prepare, sqlite3_bind_*, sqlite3_step, sqlite3_column_*, sqlite3_column_type
// sqlite3_stmt, sqlite3_finalize, sqlite3_reset
// 查询
// ----------------------------------------------
sqlite3 *conn = NULL;
sqlite3_stmt *stmt = NULL;
const char *err_msg = NULL;
// 列数据类型
char col_types[][10] = { "", "Integer", "Float", "Text", "Blob", "NULL" };

sqlite3_open("test.db", &conn);
sqlite3_prepare(conn, "SELECT * FROM [test_for_cpp] WHERE [id]>?", -1, &stmt, &err_msg);
sqlite3_bind_int(stmt, 1, 5);

while (SQLITE_ROW == sqlite3_step(stmt))
{
    int col_count = sqlite3_column_count(stmt); // 结果集中列的数量

    const char *col_0_name = sqlite3_column_name(stmt, 0); // 获取列名
    int id = sqlite3_column_int(stmt, 0);
    int id_type = sqlite3_column_type(stmt, 0); // 获取列数据类型

    const char *col_2_name = sqlite3_column_name(stmt, 2);
    int age = sqlite3_column_int(stmt, 2);
    int age_type = sqlite3_column_type(stmt, 2);

    const char *col_1_name = sqlite3_column_name(stmt, 1);
    char name[80];
    strncpy(name, (const char *)sqlite3_column_text(stmt, 1), 80);
    int name_type = sqlite3_column_type(stmt, 1);

    // 打印结果
    printf("col_count: %d, %s = %d(%s), %s = %s(%s), %s = %d(%s)/n",
        col_count, col_0_name, id, col_types[id_type], col_2_name, name,
        col_types[name_type], col_1_name, age, col_types[age_type]);
}

sqlite3_finalize(stmt); // 释放sqlite3_stmt 
sqlite3_close(conn);
这段代码查询id号大于5的全部记录.
其余函数
 在上面的例子中,还使用了其余的一些函数,
如:sqlite3_column_count用于获取结果集中列的数 量;sqlite3_column_name用于获取列的名称;
sqlite3_column_type用于获取列的数据类 型;sqlite3_errcode用于获取最近一次操做出错的错误代码;
sqlite3_errmsg用于获取最近一次操做出错的错误说明。 sqlite的api中还有不少的函数,有了上面的基础,

相信你经过查询官方的文档,能迅速掌握本文未介绍的api

 

 

5、数据库管理工具

sqlite 管理工具 Sqlite Developer

Sqlite Developer是SharpPlus出品的一款强大数据库管理软件。支持对sqlite3数据库的管理。

下载:http://dl.pconline.com.cn/download/60827.html

 Sqlite Developer 注册码http://download.csdn.net/source/2755962

 

常见问题

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

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

三、  如何查询当前的编码的编码格式
pragma  encoding;

四、  若是删除了大量数据,而又想缩小数据库文件占用的空间,执行 VACUUM 命令
vacuum;

五、  sqlite3_open打开一个数据库时,若是数据库不存在就会新生成一个数据库文件。若是接着执行其余查询语句就会失败,好比sqlite3_prepare,编程中出现明明指定了数据库并且里面也有数据,为何查询失败了,主要是数据库名路径不对引发的。通常的作法是先检查数据库文件是否存在,若是存在就使用sqlite3_open打开数据库;不然建立一个新的数据库。

六、  如何创建自动增加字段

声明为 INTEGER PRIMARY KEY 的列将会自动增加。

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

八、SQLite容许向一个integer型字段中插入字符串

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

 

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

九、为何SQLite不容许在同一个表不一样的两行上使用0和0.0做主键?

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

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

十、多个应用程序或一个应用程序的多个实例能够同时访问同一个数据库文件吗?

 

多个进程可同时打开同一个数据库。多个进程能够同时进行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 函数调整这一行为。

十一、SQLite线程安全吗?

线程是魔鬼(Threads are evil)。 避免使用它们。

SQLite 是线程安全的。因为不少用户会忽略咱们在上一段中给出的建议, 咱们作出了这种让步。可是,为了达到线程安全,SQLite在编译时必须将 SQLITE_THREADSAFE 预处理宏置为1。在Windows和Linux上,已编译的好的二进制发行版中都是这样设置的。若是不肯定你所使用的库是不是线程安全的,能够调用 sqlite3_threadsafe() 接口找出。

十二、在SQLite数据库中如何列出全部的表和索引?

若是你运行 sqlite3 命令行来访问你的数据库,能够键入 “.tables”来得到全部表的列表。或者,你能够输入 “.schema”来看整个数据库模式,包括全部的表的索引。 输入这些命令,后面跟一个LIKE模式匹配能够限制显示的表。

1三、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 个字符。

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

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

1五、在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;

 

1六、如何在Windows下编译SQLite3
1)先从官网获取sqlite-amalgamation-3_6_22.zip;

2)接着从官网获取sqlitedll-3_6_22.zip

下载编译好的DLL,这里有咱们须要的sqlite3.def该文件

3)打开VC新建一个“Win32 Dynamic-Link Library”工程,命名为:sqlite3;

4)在接下来的对话框中选择"An empty DLL project",点 FINISH->OK;

5)将sqlite-amalgamation-3_6_22文件夹下的sqlite3.h以及sqlite3.c两个文件复制到工程文件夹下;

       将sqlitedll-3_6_22文件夹下的sqlite3.def该文件复制到工程文件夹下;

6)在工程的Source Files中添加sqlite3.c文件;

7)在工程的Include Files中添加sqlite3.h文件;

8)在工程的Resource Files中添加sqlite3.def文件;

9)针对以下问题:

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_database_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_database_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_origin_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_origin_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_table_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_table_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_table_column_metadata

Debug/sqlite3.lib : fatal error LNK1120: 7 unresolved externals

在菜单【Project】-【Settings…】-【C/C++】标签下的Category【General】下

Preprocessor definitions下:

新增2个编译选项,分别是:

THREADSAFE

SQLITE_ENABLE_COLUMN_METADATA

10)往工程中添加sqlite3.def文件就是为生成sqlite3.lib文件;

sqlite3.lib是与sqlite3.dll动态连接库文件一块儿提供给软件开发者的;

11)解决Windows下的编译警告
e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'long *'

e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 1

e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 2

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'long *'

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 1

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 3

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4047: '==' : 'void *' differs in levels of indirection from 'const int '

e:/sqlite/code/sqlite3/sqlite3.c(65536) : warning C4049: compiler limit : terminating line number emission

warning C4761: integral size mismatch in argument; conversion supplied

warning C4761: integral size mismatch in argument; conversion supplied

warning C4761: integral size mismatch in argument; conversion supplied

 

VC2005 + SQLite 3.6.3 编译、测试开发

http://blog.csdn.net/Dreamcode/archive/2009/08/21/4467277.aspx

 

参考资料:

sqlite 中文社区:http://www.sqlite.com.cn/

sqlite 官方网站:http://www.sqlite.org/

相关文章
相关标签/搜索