注意: 本文档编写于 2004 年,旨在帮助程序员从使用 SQLite 版本 2 迁移到 SQLite 版本 3。本文档中的信息基本上仍然是正确的,但是多年来发生了许多变化和增强。我们建议改用以下文件:

SQLite 版本 3 的 C/C++ 接口

1.0 概述

SQLite 3.0 版是 SQLite 的新版本,源自 SQLite 2.8.13 代码库,但具有不兼容的文件格式和 API。SQLite 3.0 版的创建是为了满足对以下功能的需求:

必须迁移到 3.0 版才能实现这些功能,因为每个功能都需要对数据库文件格式进行不兼容的更改。其他不兼容的更改,例如 API 的清理,是在最好一次将不兼容的更改全部清除的理论下同时引入的。

3.0 版的 API 类似于 2.X 版的 API,但有一些重要的变化。最值得注意的是,出现在所有 API 函数和数据结构开头的“ sqlite_ ”前缀被更改为“ sqlite3_ ”。这避免了两个 API 之间的混淆,并允许同时链接到 SQLite 2.X 和 SQLite 3.0。

对于 UTF-16 字符串的 C 数据类型应该是什么没有达成一致。因此,SQLite 使用泛型类型 void* 来引用 UTF-16 字符串。客户端软件可以将 void* 转换为适合其系统的任何数据类型。

2.0 C/C++ 接口

SQLite 3.0 的 API 除了几个数据结构和#defines 之外,还包括 83 个独立的函数。(完整的 API 参考作为单独的文档提供。)幸运的是,接口并不像它的大小所暗示的那么复杂。简单的程序仍然可以只使用 3 个函数: sqlite3_open()sqlite3_exec()sqlite3_close()使用sqlite3_prepare_v2() 将 SQLite 语句编译成字节码并 使用sqlite3_step()执行该字节码,可以更好地控制数据库引擎的执行。一系列名称以 sqlite3_column_开头的例程 用于提取有关查询结果集的信息。许多接口函数成对出现,同时具有 UTF-8 和 UTF-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() 例程返回一个整数错误代码,而不是像版本 2 接口那样返回一个指向 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 的错误消息。

SQLite 版本 3 的错误代码与版本 2 相同,如下所示:

#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()函数的工作方式与它在 SQLite 版本 2 中的工作方式非常相似。编译并执行第二个参数中指定的零个或多个 SQL 语句查询结果返回到回调例程。

在 SQLite 版本 3 中,sqlite3_exec 例程只是对准备语句接口调用的包装。

   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 语句编译成字节码供以后执行。该接口现在是访问数据库的首选方式。

SQL 语句是 sqlite3_prepare() 的 UTF-8 字符串。sqlite3_prepare16() 的工作方式相同,只是它需要一个 UTF-16 字符串作为 SQL 输入。仅编译输入字符串中的第一条 SQL 语句。第五个参数用指向输入字符串中下一个(未编译的)SQLite 语句的指针填充,如果有的话。sqlite3_finalize() 例程释放准备好的 SQL 语句。在关闭数据库之前,必须完成所有准备好的语句。sqlite3_reset() 例程重置准备好的 SQL 语句,以便它可以再次执行。

SQL 语句可能包含“?”形式的标记。或“?nnn”或“:aaa”,其中“nnn”是一个整数,“aaa”是一个标识符。此类标记表示未指定的文字值(或“通配符”),稍后将由 sqlite3_bind接口填充。每个通配符都有一个关联的数字,它是它在语句中的序列,或者在“?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 语句中为通配符赋值。未绑定的通配符被解释为 NULL。sqlite3_reset() 不会重置绑定。但是通配符可以在 sqlite3_reset() 之后重新绑定到新值。

准备好(并可选地绑定)SQL 语句后,使用以下命令执行它:

   int sqlite3_step(sqlite3_stmt*);

sqlite3_step() 例程如果返回结果集的单行则返回 SQLITE_ROW,如果执行已完成(正常或由于错误)则返回 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_v2()之后随时调用 sqlite3_data_count()的工作方式与sqlite3_column_count()类似, 只是它仅在sqlite3_step()之后工作。如果先前对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() 返回具有 BLOB 类型的列中的字节数或使用 UTF-8 编码的 TEXT 字符串中的字节数。sqlite3_column_bytes16() 为 BLOB 返回相同的值,但为 TEXT 字符串返回 UTF-16 编码中的字节数。sqlite3_column_blob() 返回 BLOB 数据。sqlite3_column_text() 以 UTF-8 格式返回文本数据。sqlite3_column_text16() 以 UTF-16 格式返回文本数据。sqlite3_column_int() 以主机本机整数格式返回 INTEGER 数据。sqlite3_column_int64() 返回 64 位 INTEGER 数据。最后,sqlite3_column_double() 返回浮点数据。

不必以 sqlite3_column_type() 指定的格式检索数据。如果请求不同的格式,数据会自动转换。

数据格式转换会使先前调用 sqlite3_column_blob()、sqlite3_column_text() 和/或 sqlite3_column_text16() 返回的指针无效。在以下情况下,指针可能会失效:

请注意,UTF-16be 和 UTF-16le 之间的转换始终在适当的位置完成,并且不会使先前的指针无效,尽管当然先前指针指向的缓冲区的内容将被修改。其他类型的转换在可能的情况下就地完成,但有时是不可能的,在这些情况下,先前的指针将失效。

最安全和最容易记住的策略是:假设任何结果来自

被后续调用无效 这意味着您应该始终在调用 sqlite3_column_blob()、sqlite3_column_text() 或 sqlite3_column_text16()之前调用 sqlite3_column_bytes() 或 sqlite3_column_bytes16()。

2.3 用户自定义函数

可以使用以下例程创建用户定义的函数:

   typedef struct sqlite3_value sqlite3_value;
   int sqlite3_create_function(
     sqlite3 *,
     const char *zFunctionName,
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   int sqlite3_create_function16(
     sqlite3*,
     const void *zFunctionName,
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   #define SQLITE_UTF8     1
   #define SQLITE_UTF16    2
   #define SQLITE_UTF16BE  3
   #define SQLITE_UTF16LE  4
   #define SQLITE_ANY      5

nArg 参数指定函数的参数数量。值 0 表示允许任意数量的参数。eTextRep 参数指定此函数的参数预期包含的表示文本值。该参数的值应该是上面定义的参数之一。SQLite 版本 3 允许使用不同的文本表示法对同一函数进行多种实现。数据库引擎选择最小化所需文本转换次数的函数。

普通函数仅指定 xFunc 并将 xStep 和 xFinal 设置为 NULL。聚合函数指定 xStep 和 xFinal 并将 xFunc 设置为 NULL。没有单独的 sqlite3_create_aggregate() API。

函数名称以 UTF-8 格式指定。单独的 sqlite3_create_function16() API 与 sqlite_create_function() 的工作方式相同,只是函数名称以 UTF-16 主机字节顺序指定。

请注意,函数的参数现在是指向 sqlite3_value 结构的指针,而不是像 SQLite 版本 2.X 中那样指向字符串的指针。以下例程用于从这些“值”中提取有用的信息:

   const void *sqlite3_value_blob(sqlite3_value*);
   int sqlite3_value_bytes(sqlite3_value*);
   int sqlite3_value_bytes16(sqlite3_value*);
   double sqlite3_value_double(sqlite3_value*);
   int sqlite3_value_int(sqlite3_value*);
   long long int sqlite3_value_int64(sqlite3_value*);
   const unsigned char *sqlite3_value_text(sqlite3_value*);
   const void *sqlite3_value_text16(sqlite3_value*);
   int sqlite3_value_type(sqlite3_value*);

函数实现使用以下 API 来获取上下文并报告结果:

   void *sqlite3_aggregate_context(sqlite3_context*, int nbyte);
   void *sqlite3_user_data(sqlite3_context*);
   void sqlite3_result_blob(sqlite3_context*, const void*, int n, void(*)(void*));
   void sqlite3_result_double(sqlite3_context*, double);
   void sqlite3_result_error(sqlite3_context*, const char*, int);
   void sqlite3_result_error16(sqlite3_context*, const void*, int);
   void sqlite3_result_int(sqlite3_context*, int);
   void sqlite3_result_int64(sqlite3_context*, long long int);
   void sqlite3_result_null(sqlite3_context*);
   void sqlite3_result_text(sqlite3_context*, const char*, int n, void(*)(void*));
   void sqlite3_result_text16(sqlite3_context*, const void*, int n, void(*)(void*));
   void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
   void *sqlite3_get_auxdata(sqlite3_context*, int);
   void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));

2.4 用户定义的整理顺序

以下例程用于实现用户定义的整理序列:

   sqlite3_create_collation(sqlite3*, const char *zName, int eTextRep, void*,
      int(*xCompare)(void*,int,const void*,int,const void*));
   sqlite3_create_collation16(sqlite3*, const void *zName, int eTextRep, void*,
      int(*xCompare)(void*,int,const void*,int,const void*));
   sqlite3_collation_needed(sqlite3*, void*, 
      void(*)(void*,sqlite3*,int eTextRep,const char*));
   sqlite3_collation_needed16(sqlite3*, void*,
      void(*)(void*,sqlite3*,int eTextRep,const void*));

sqlite3_create_collat​​ion() 函数指定了一个整理序列名称和一个比较函数来实现该整理序列。比较函数仅用于比较文本值。eTextRep 参数是 SQLITE_UTF8、SQLITE_UTF16LE、SQLITE_UTF16BE 或 SQLITE_ANY 之一,用于指定比较函数使用的文本表示形式。每个 UTF-8、UTF-16LE 和 UTF-16BE 文本表示的相同整理序列可以存在单独的比较函数。sqlite3_create_collat​​ion16() 的工作方式与 sqlite3_create_collat​​ion() 类似,只是排序规则名称是以 UTF-16 主机字节顺序而不是 UTF-8 指定的。

sqlite3_collat​​ion_needed() 例程注册了一个回调,如果数据库引擎遇到未知的整理顺序,它将调用该回调。回调可以查找适当的比较函数并根据需要调用 sqlite_3_create_collat​​ion()。回调的第四个参数是 UTF-8 中的整理序列的名称。对于 sqlite3_collat​​ion_need16() 回调以 UTF-16 主机字节顺序发送整理序列名称。