当前位置:   article > 正文

数据库 -- SQLite3详解_sqllite license

sqllite license

一.准备工作
Sqlite官网地址:http://www.sqlite.org,截止目前的最新版本:3.7.14。
下载Sqlite源码及对应版本的文档:sqlite-amalgamation-3071400.zip,sqlite-doc-3071400.zip
解压源码压缩包,释放出4个文件:shell.c sqlite3.c sqlite3.h sqlite3ext.h
开始编译!(windows平台,vs2005)
         首先用vs建一个工程,我的目标是编译成lib,所以建一个静态库工程,工程建好后将解压出来的4个文件加入工程,编译,生成lib文件。
编译选项:
关于编译选项的设置compile.html文档中有介绍,选项很多,慢慢看。
其中有一个SQLITE_THREADSAFE=<0 or 1 or 2>选项决定了多线程环境下的安全问题,
0 多线程不安全。
1 多线程安全。
2 可以在多线程中使用,但多线程之间不能共享database connection和任何从其派生的prepared statements。
默认SQLITE_THREADSAFE=1
如果使用的是别人编译好的dll或lib,自己不知道编译选项里设置的值,别着急,可以调用sqlite3_threadsafe()取得设置。
还可以调用sqlite3_config()修改设置。
 
二.使用SQLite3的C/C++接口
两个常用的对象:
The database connection object: sqlite3
The prepared statement object: sqlite3_stmt
 
常用的接口:
sqlite3_open()
通常这个函数被第一个调用,这个操作打开一个数据库文件的链接,输出一个database connection对象,database connection对象在调用之后的接口时使用。
函数原型:
int sqlite3_open(
 const char *filename,   /*Database filename (UTF-8) */
 sqlite3 **ppDb          /* OUT:SQLite db handle */
);
int sqlite3_open16(
 const void *filename,   /*Database filename (UTF-16) */
 sqlite3 **ppDb          /* OUT:SQLite db handle */
);
int sqlite3_open_v2(
  constchar *filename,   /* Database filename(UTF-8) */
 sqlite3 **ppDb,         /* OUT:SQLite db handle */
  intflags,              /* Flags */
 const char *zVfs        /* Name ofVFS module to use */
);
通过filename参数指定要打开的数据库,sqlite3_open()和sqlite3_open_v2()的filename参数是utf8编码格式,sqlite3_open16()的filename参数是UTF-16编码。
如果成功,sqlite3*被创建,返回值SQLITE_OK,如果失败,返回错误码,调用sqlite3_errmsg() 或 sqlite3_errmsg16()将得到错误信息。
无论成功与否, database connection句柄资源已经被分配,在不使用时应该将数据库连接句柄传递给sqlite3_close()释放资源。
 
sqlite3_open_v2的第三个参数,有3个值和其他的值(SQLITE_OPEN_NOMUTEX, SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_SHAREDCACHE,SQLITE_OPEN_PRIVATECACHE, and/or SQLITE_OPEN)组合:
SQLITE_OPEN_READONLY
SQLITE_OPEN_READWRITE
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
如何不是用上面的3个值之一和其他值组合,其行为是未定义的。
 
sqlite3_prepare()
这个操作第一个参数输入database connection对象,第二个参数输入sql语句,该接口将输入的sql语句转变成prepared statement对象,输出prepared statement对象,在调用之后的接口时使用,记住,这个函数不执行sql语句,只为执行sql做准备。
函数原型:
int sqlite3_prepare(
 sqlite3 *db,            /*Database handle */
 const char *zSql,       /* SQLstatement, UTF-8 encoded */
  intnByte,              /* Maximum length ofzSql in bytes. */
 sqlite3_stmt **ppStmt,  /* OUT:Statement handle */
 const char **pzTail     /* OUT:Pointer to unused portion of zSql */
);
int sqlite3_prepare_v2(
 sqlite3 *db,            /*Database handle */
 const char *zSql,       /* SQLstatement, UTF-8 encoded */
  intnByte,              /* Maximum length of zSql in bytes. */
 sqlite3_stmt **ppStmt,  /* OUT:Statement handle */
 const char **pzTail     /* OUT:Pointer to unused portion of zSql */
);
int sqlite3_prepare16(
 sqlite3 *db,            /*Database handle */
 const void *zSql,       /* SQLstatement, UTF-16 encoded */
  intnByte,              /* Maximum length ofzSql in bytes. */
 sqlite3_stmt **ppStmt,  /* OUT:Statement handle */
 const void **pzTail     /* OUT:Pointer to unused portion of zSql */
);
int sqlite3_prepare16_v2(
 sqlite3 *db,            /*Database handle */
 const void *zSql,       /* SQLstatement, UTF-16 encoded */
  intnByte,              /* Maximum length ofzSql in bytes. */
 sqlite3_stmt **ppStmt,  /* OUT:Statement handle */
  const void **pzTail     /* OUT: Pointer to unused portion of zSql*/
);
 
sqlite3_step()
这个操作执行sqlite3_prepare()接口返回的prepared statement,如果是SELECT操作,结果集的第一行将被返回,如果想得到第二行,还须再调用一次该函数,也就是每调用一次返回一行,直到完成。
有些操作仅需调用1次该函数,如:INSERT, UPDATE, DELETE语句。
使用老接口得到的statement,执行sqlite3_step返回SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE;
使用v2接口得到的statement,执行sqlite3_step返回任意的result code或extended result codes。
 
sqlite3_column()
sqlite3接口并没有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_step()的prepared statement对象,返回单列的结果,要得到一行中全部列的值需要调用多次这个函数。
 
sqlite3_finalize()
销毁之前调用sqlite3_prepare()创建的prepared statement,prepared statement必须由该函数销毁,否则会导致内存泄露。
 
sqlite3_close()
关闭之前调用sqlite3_open()创建的database connection,在调用该函数之前,必须保证所有的prepared statements都被finalized。
 
开发SQLite应用一般的流程:
首先用sqlite3_open()创建一个数据库连接,该函数根据输入参数可以打开一个已存在的数据库,也可以创建一个新的数据库文件。不用数据库的时候记得调用 sqlite3_close() 关闭数据库连接。
执行一个SQL statement,有以下步骤:
1. 调用sqlite3_prepare()创建 preparedstatement。
2. 调用sqlite3_step()一次或多次执行preparedstatement。
3. 对于查询操作,在两次sqlite3_step()之间调用sqlite3_column()获取结果。
4. 调用sqlite3_finalize()销毁preparedstatement。
 
在调用 sqlite3_step()之后,可以调用sqlite3_reset()初始化prepared statement。
很多时候,每次调用的sql语句都是相似的,比如使用INSERT语句,每次执行只是插入不同的值,为了适应这种灵活性,SQLite允许SQL statements带参数,在执行statements前给这些参数绑定一个值,绑定的值在 prepared statement第二次执行的时候还可以改变。
 
获得错误信息的函数:
int sqlite3_errcode(sqlite3 *db);
int sqlite3_extended_errcode(sqlite3 *db);
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
 
三.SQLite3的线程模式

    为了达到线程安全,SQLite在编译时必须将 SQLITE_THREADSAFE 预处理宏置为1。在Windows和Linux上, 已编译的好的二进制发行版中都是这样设置的。 如果不确定你所使用的库是否是线程安全的,可以调用 sqlite3_threadsafe() 接口找出。调用sqlite3_threadsafe()可以获得编译期的SQLITE_THREADSAFE参数 。

   也就是说线程模式可以在编译时(通过源码编译sqlite库时)、启动时(使用sqlite的应用程序初始化时)或者运行时(创建数据库连接时)来指定。一般而言,运行时指定的模式将覆盖启动时的指定模式,启动时指定的模式将覆盖编译时指定的模式。但是,单线程模式一旦被指定,将无法被覆盖。默认的线程模式是串行模式。


编译时选择线程模式
    可以通过定义SQLITE_THREADSAFE宏来指定线程模式。如果没有指定,默认为串行模式。定义宏SQLITE_THREADSAFE=1指定使用串行模式;=0使用单线程模式;=2使用多线程模式。
    sqlite3_threadsafe()函数的返回值可以确定编译时指定的线程模式。如果指定了单线程模式,函数返回false。如果指定了串行或者多线程模式,函数返回true。由于sqlite3_threadsafe()函数要早于多线程模式以及启动时和运行时的模式选择,所以它既不能区别多线程模式和串行模式也不能区别启动时和运行时的模式。
    最后一句可通过sqlite3_threadsafe函数的实现来理解SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }如果编译时指定了单线程模式,那么临界互斥逻辑在构造时就被省略,因此也就无法在启动时或运行时指定串行模式或多线程模式。

启动时选择线程模式
    假如在编译时没有指定单线程模式,就可以在应用程序初始化时使用sqlite3_config()函数修改线程模式。参数SQLITE_CONFIG_SINGLETHREAD可指定为
单线程模式,SQLITE_CONFIG_MULTITHREAD指定为多线程模式,SQLITE_CONFIG_SERIALIZED指定为串行模式。

运行时选择线程模式
    如果没有在编译时和启动时指定为单线程模式,那么每个数据库连接在创建时可单独的被指定为多线程模式或者串行模式,但是不能指定为单线程模式。如果在编译时或启动时指定为单线程模式,就无法在创建连接时指定多线程或者串行模式。
    创建连接时用sqlite3_open_v2()函数的第三个参数来指定线程模式。SQLITE_OPEN_NOMUTEX标识创建多线程模式的连接;SQLITE_OPEN_FULLMUTEX标识创建串行模式的连接。如果没有指定标识,或者使用sqlite3_open()或sqlite3_open16()函数来创建数据库连接,那么在编译时或启动时指定的线程模式将作为默认的线程模式使用。


运行时设置线程模式:
如果Single-thread模式在编译时和启动时都没被设置,则可以在database connections被创建时设置Multi-thread或Serialized模式,但不可以降级设置为Single-thread模式,也不可以升级编译时或启动时设置的Single-thread模式。
sqlite3_open_v2()的第三个参数决定单个databaseconnection的线程模式,SQLITE_OPEN_NOMUTEX使database connection为Multi-thread模式,SQLITE_OPEN_FULLMUTE使database connection为Serialized模式。
如果不指定模式或使用sqlite3_open()或sqlite3_open16()接口,线程模式为编译时或启动时设置的模式。

四.其它需要注意的

1. 如果需要用sqlite的*16函数(e.g. sqlite3_prepare16) ,需要传入 UTF-16 (i.e. wstring) 参数,一定要用 2*wcslen 作为字符穿长度传入,否则会被截断。

2. 对多个表同时操作时,为每个表建一个connection要比共享connection好,减小了冲突的可能性。


from:http://blog.csdn.net/hzyong_c/article/details/8010647

            http://blog.sina.com.cn/s/blog_a459dcf50101496d.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/490939
推荐阅读
相关标签
  

闽ICP备14008679号