注意: 本文档编写于 2004 年,旨在帮助程序员从使用 SQLite 版本 2 迁移到 SQLite 版本 3。本文档中的信息基本上仍然是正确的,但是多年来发生了许多变化和增强。我们建议改用以下文件:
SQLite 版本 3 的 C/C++ 接口
1.0 概述
SQLite 3.0 版是 SQLite 的新版本,源自 SQLite 2.8.13 代码库,但具有不兼容的文件格式和 API。SQLite 3.0 版的创建是为了满足对以下功能的需求:
- 支持 UTF-16。
- 用户可定义的文本整理顺序。
- 在索引列中存储 BLOB 的能力。
必须迁移到 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() 返回的指针无效。在以下情况下,指针可能会失效:
初始内容是 BLOB 并调用 sqlite3_column_text() 或 sqlite3_column_text16()。可能需要将零终止符添加到字符串中。
初始内容是 UTF-8 文本,调用 sqlite3_column_bytes16() 或 sqlite3_column_text16()。内容必须转换为 UTF-16。
初始内容是 UTF-16 文本,调用了 sqlite3_column_bytes() 或 sqlite3_column_text()。内容必须转换为 UTF-8。
请注意,UTF-16be 和 UTF-16le 之间的转换始终在适当的位置完成,并且不会使先前的指针无效,尽管当然先前指针指向的缓冲区的内容将被修改。其他类型的转换在可能的情况下就地完成,但有时是不可能的,在这些情况下,先前的指针将失效。
最安全和最容易记住的策略是:假设任何结果来自
- sqlite3_column_blob(),
- sqlite3_column_text() 或
- sqlite3_column_text16()
- sqlite3_column_bytes(),
- sqlite3_column_bytes16(),
- sqlite3_column_text() 或
- sqlite3_column_text16()。
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 主机字节顺序发送整理序列名称。