小巧。快速。可靠。
三选二。

注意:本文档于 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 包括 83 个独立的函数,以及几个数据结构和 #define。(完整的 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 语句编译成字节码以供以后执行。此接口现在是访问数据库的首选方式。

对于 sqlite3_prepare(),SQL 语句是 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_prepare_v2() 之后随时调用 sqlite3_column_count()。 sqlite3_data_count() 的工作方式类似于 sqlite3_column_count(),只是它仅在 sqlite3_step() 之后才有效。如果对 sqlite3_step() 的上一次调用返回 SQLITE_DONE 或错误代码,则 sqlite3_data_count() 将返回 0,而 sqlite3_column_count() 将继续返回结果集中列的数量。

使用其他 sqlite3_column_***() 函数检查返回的数据,所有这些函数都将列号作为其第二个参数。列从左到右从 0 开始索引。请注意,这与参数不同,参数从 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 返回 TEXT 数据。sqlite3_column_text16() 以 UTF-16 返回 TEXT 数据。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_collation() 函数指定排序规则名称和一个比较函数来实现该排序规则。比较函数仅用于比较文本值。eTextRep 参数是 SQLITE_UTF8、SQLITE_UTF16LE、SQLITE_UTF16BE 或 SQLITE_ANY 之一,用于指定比较函数使用的文本表示形式。对于每个 UTF-8、UTF-16LE 和 UTF-16BE 文本表示形式,可以为相同的排序规则存在单独的比较函数。sqlite3_create_collation16() 的工作方式与 sqlite3_create_collation() 相同,只是排序规则名称以 UTF-16 主机字节序而不是 UTF-8 指定。

sqlite3_collation_needed() 例程注册了一个回调函数,如果数据库引擎遇到未知的排序规则,它将调用该回调函数。回调函数可以查找合适的比较函数,并在需要时调用 sqlite_3_create_collation()。回调函数的第四个参数是以 UTF-8 表示的排序规则名称。对于 sqlite3_collation_need16(),回调函数以 UTF-16 主机字节序发送排序规则名称。

此页面最后修改于 2022-01-08 05:02:57 UTC