SQLite剖析之编程接口详解
前言
使用过程根据函数大致分为如下几个过程:
- sqlite3_open()
- sqlite3_prepare()
- sqlite3_step()
- sqlite3_column()
- sqlite3_finalize()
- sqlite3_close()
这几个过程是概念上的说法,而不完全是程序运行的过程,如sqlite3_column()表示的是对查询获得一行里面的数据的列的各个操作统称,实际上在sqlite中并不存在这个函数。
1.sqlite3_open()
该函数用来打开数据库。在操作数据库之前,首先要打开数据库。这个函数打开一个sqlite数据库文件的连接并且返回一个数据库连接对象。这个操作同时程序中的第一个调用的sqlite函数,同时也是其他sqlite api的先决条件。许多的sqlite接口函数都需要一个数据库连接对象的指针作为它们的第一个参数。
函数定义:
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(const char *filename, /* Database filename (UTF-8) */sqlite3 **ppDb, /* OUT: SQLite db handle */int flags, /* Flags */const char *zVfs /* Name of VFS module to use */ );
说明:
假如这个要被打开的数据文件不存在,则一个同名的数据库文件将被创建。如果使用sqlite3_open和sqlite3_open_v2的话,数据库将采用UTF-8的编码方式,sqlite3_open16采用UTF-16的编码方式。
返回值:
如果sqlite数据库被成功打开(或创建),将会返回SQLITE_OK,否则将会返回错误码。Sqlite3_errmsg()或者sqlite3_errmsg16可以用于获得数据库打开错误码的英文描述,这两个函数定义为:
const char *sqlite3_errmsg(sqlite3*); const void *sqlite3_errmsg16(sqlite3*);
无论是否成功打开数据库, 都应该使用 sqlite3_close()关闭数据库连接。
参数说明:
filename:需要被打开的数据库文件的文件名,在sqlite3_open和sqlite3_open_v2中这个参数采用UTF-8编码,而在sqlite3_open16中则采用UTF-16编码。
ppDb:一个数据库连接句柄被返回到这个参数,即使发生错误。唯一的异常是如果sqlite不能分配内存来存放sqlite对象,ppDb将会被返回一个NULL值。
flags:作为数据库连接的额外控制的参数,可以是SQLITE_OPEN_READONLY、SQLITE_OPEN_READWRITE和SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE中的一个,用于控制数据库的打开方式,可以和SQLITE_OPEN_NOMUTEX、SQLITE_OPEN_FULLMUTEX、 SQLITE_OPEN_SHAREDCACHE以及SQLITE_OPEN_PRIVATECACHE结合使用,具体的详细情况可以查阅文档。
2.Sqlite3_prepare()
这个函数将sql文本转换成一个准备语句(prepared statement)对象,同时返回这个对象的指针。这个接口需要一个数据库连接指针以及一个要准备的包含SQL语句的文本。它实际上并不执行(evaluate)这个SQL语句,它仅仅为执行准备这个sql语句。
函数定义(仅列出UTF-8的):
int sqlite3_prepare(sqlite3 *db, /* Database handle */ /* 成功打开的数据库句柄 */const char *zSql, /* SQL statement, UTF-8 encoded */ /* UTF8编码的 SQL 语句 */int nByte, /* Maximum length of zSql in bytes. */ /* 参数 sql 的字节数, 包含 '\0' */sqlite3_stmt **ppStmt, /* OUT: Statement handle */ /* 输出:预编译语句句柄 */const char **pzTail /* OUT: Pointer to unused portion of zSql */ /* 输出:指向 sql 语句中未使用的部分 */ ); int sqlite3_prepare_v2(sqlite3 *db, /* Database handle */const char *zSql, /* SQL statement, UTF-8 encoded */int nByte, /* Maximum length of zSql in bytes. */sqlite3_stmt **ppStmt, /* OUT: Statement handle */const char **pzTail /* OUT: Pointer to unused portion of zSql */ );
参数说明:
db:数据库指针。
zSql:sql语句,使用UTF-8编码。
nByte:如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值;如果nBytes非负,zSql在第一次遇见’/000/或’u000’的时候终止。如果用户知道被传入的sql语句是以 '\0' 结尾的,那么有一个更好的做法是:把nbytes的值设为该字符串的长度(包含'\0'),这样可以避免SQLite复制该字符串的一份拷贝,以提高程序的效率。
pzTail:上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符。如果pszTail不为NULL, 则*pszTail指向sql中第一个被传入的SQL语句的结尾。该函数只编译sql的第一个语句, 所以*pszTail指向的内容则是未被编译的。
ppStmt:能够使用sqlite3_step()执行的编译好的准备语句的指针,如果错误发生,它被置为NULL,如假如输入的文本不包括sql语句。调用过程必须负责在编译好的sql语句完成使用后使用sqlite3_finalize()删除它。
说明:
如果执行成功,则返回SQLITE_OK,否则返回一个错误码。推荐使用sqlite3_prepare_v2这个函数,sqlite3_prepare只是用于前向兼容。
备注:
<1>准备语句(prepared statement)对象
typedef struct sqlite3_stmt sqlite3_stmt;
一个准备语句(prepared statement)对象代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。
语句对象的生命周期经历这样的过程:
- 使用sqlite3_prepare_v2或相关的函数创建这个对象
- 使用sqlite3_bind_*()给宿主参数(host parameters)绑定值
- 通过调用sqlite3_step一次或多次来执行这个sql
- 使用sqlite3——reset()重置这个语句,然后回到第2步,这个过程做0次或多次
- 使用sqlite3_finalize()销毁这个对象
在sqlite中并没有定义sqlite3_stmt这个结构的具体内容,它只是一个抽象类型,在使用过程中一般以它的指针进行操作,而sqlite3_stmt类型的指针在实际上是一个指向Vdbe的结构体得指针。
<2>宿主参数(host parameters)
在传给sqlite3_prepare_v2()的sql的语句文本或者它的变量中,满足如下模板的文字将被替换成一个参数:
| ? | ?NNN //NNN代表数字 | :VVV //VVV代表字符 | @VVV | $VVV
在上面这些模板中,NNN代表一个数字,VVV代表一个字母数字标记符(例如:222表示名称为222的标记符),sql语句中的参数(变量)通过上面的几个模板来指定,如“select ? from ? “这个语句中指定了两个参数,sqlite语句中的第一个参数的索引值是1,这就知道这个语句中的两个参数的索引分别为1和2,使用”?”的话会被自动给予索引值,而使用”?NNN”则可以自己指定参数的索引值,它表示这个参数的索引值为NNN。”:VVV”表示一个名为”VVV”的参数,它也有一个索引值,被自动指定。
例如:
INSERT INTO people (id, name) VALUES ( ?, ? ); INSERT INTO people (id, id2,name) VALUES ( ?1, ?1.?2 ); //作用:可以用同一个值绑定几个变量 INSERT INTO people (id, name) VALUES ( :id, :name ); INSERT INTO people (id, name) VALUES ( @id, @name ); INSERT INTO people (id, name) VALUES ( $id, $name ); //用来支持Tcl变量的扩展语法,除非使用Tcl编程,否则推荐使用“:<name>”版本
可以使用sqlite3_bind_*()来给这些参数绑定值。
3.int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n,void(*)(void*))
参数说明:
第二个参数:为序号(从1开始)
第三个参数:为字符串值
第四个参数:为字符串长度
第五个参数:为一个函数指针,SQLITE3执行完操作后回调此函数,通常用于释放字符串占用的内存。此参数有两个常数,SQLITE_STATIC告诉sqlite3_bind_text函数字符串为常量,可以放心使用;而SQLITE_TRANSIENT会使得sqlite3_bind_text函数对字符串做一份拷贝。一般使用这两个常量参数来调sqlite3_bind_text。statement准备好了以后,就是操作的执行了。
sqlite3_bind_*系列函数还有好多:
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); //功能:为查询结构体绑定数据
参数说明:
PARAM1(IN):查询结构体。
PARAM2(IN):绑定第几个数据(sql语句中的第几个问号(?))。
PARAM3(IN):二进制数据指针。
PARAM4(IN):二进制数据长度。
PARAM5(IN):析构回调函数,通常设置NULL,结束后自己释放。
返回值:
SQLITE_OK 成功。
说明:
绑定函数必须要在sqlite3_step前,sqlite3_prepare或者sqlite3_reset之后调用。
未绑定的参数缺省为NULL,类似的绑定函数还有以下:
int sqlite3_bind_double(sqlite3_stmt*, int, double); int sqlite3_bind_int(sqlite3_stmt*, int, int); int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite_int64); 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, void(*)(void*)); int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
4. sqlite3_step()
这个过程用于执行有前面sqlite3_prepare创建的准备语句。这个语句执行到结果的第一行可用的位置。继续前进到结果的第二行的话,只需再次调用sqlite3_setp()。继续调用sqlite3_setp()直到这个语句完成,那些不返回结果的语句(如:INSERT、UPDATE或DELETE),sqlite3_step()只执行一次就返回。
函数定义:
int sqlite3_step(sqlite3_stmt*);
返回值:
函数的返回值基于创建sqlite3_stmt参数所使用的函数,假如是使用老版本的接口sqlite3_prepare()和sqlite3_prepare16(),返回值会是SQLITE_BUSY、SQLITE_DONE、SQLITE_ROW、SQLITE_ERROR或 SQLITE_MISUSE,而v2版本的接口sqlite3_prepare_v2()和sqlite3_prepare16_v2()则会同时返回这些结果码和扩展结果码。
对所有V3.6.23.1以及其前面的所有版本,需要在sqlite3_step()之后调用sqlite3_reset(),在后续的sqlite3_ step之前。如果调用sqlite3_reset重置准备语句失败,将会导致sqlite3_ step返回SQLITE_MISUSE,但是在V3. 6.23.1以后,sqlite3_step()将会自动调用sqlite3_reset。
说明:
当一条语句被sqlite3_prepare()或其相关的函数预编译后,sqlite3_step()必须被调用一次或多次来评估该预编译语句。
该函数的详细行为依赖于由sqlite3_prepare()(或其相关的函数)产生的是一条怎样的预编译语句。
函数将返回一个以下的结果来标识其执行结果:
SQLITE_BUSY:忙碌. 数据库引擎无法锁定数据去完成其工作. 但可以多次尝试.
SQLITE_DONE:完成. sql 语句已经被成功地执行. 在调用 sqlite_reset() 之前, 当前预编译的语句不应该被 sqlite3_step() 再次调用.
SQLITE_ROW:查询时产生了结果. 此时可以通过相关的"数据访问函数(column access functions)"来取得数据. sqlite3_step() 的再一次调用将取得下一条查询结果.
SQLITE_ERROR:发生了错误. 此时可以通过 sqlite3_errmmsg() 取得相关的错误信息. sqlite3_step() 不能被再次调用.
SQLITE_MISUSE:不正确的库的使用. 该函数使用不当.
5.int sqlite3_reset(sqlite3_stmt *pStmt)
sqlite3_reset用于重置一个准备语句对象到它的初始状态,然后准备被重新执行。所有sql语句变量使用sqlite3_bind*绑定值,使用sqlite3_clear_bindings重设这些绑定。Sqlite3_reset接口重置准备语句到它代码开始的时候。sqlite3_reset并不改变在准备语句上的任何绑定值,那么这里猜测,可能是语句在被执行的过程中发生了其他的改变,然后这个语句将它重置到绑定值的时候的那个状态。
返回值:
它的返回值相对有些特殊。返回SQLITE_BUSY表示暂时无法执行操作,SQLITE_DONE表示操作执行完毕,SQLITE_ROW表示执行完毕并且有返回(执行select语句时)。当返回值为SQLITE_ROW时,我们需要对查询结果进行处理,SQLITE3提供sqlite3_column_*系列函数。
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
参数:
iCol为列的序号,从0开始。
返回值:
如果返回值有多行,则可以再次调用sqlite3_step函数,然后由sqlite3_column_*函数取得返回值。
6. sqlite3_column()
这个过程从执行sqlite3_step()执行一个准备语句得到的结果集的当前行中返回一个列。每次sqlite3_step得到一个结果集的列停下后,这个过程就可以被多次调用去查询这个行的各列的值。对列操作是有多个函数,均以sqlite3_column为前缀:
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); double sqlite3_column_double(sqlite3_stmt*, int iCol); int sqlite3_column_int(sqlite3_stmt*, int iCol); sqlite3_int64 sqlite3_column_int64(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); int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol); sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
说明:
第一个参数为从sqlite3_prepare返回来的prepared statement对象的指针,第二参数指定这一行中的想要被返回的列的索引。最左边的一列的索引号是0,行的列数可以使用sqlite3_colum_count()获得。
这些过程会根据情况去转换数值的类型,sqlite内部使用sqlite3_snprintf()去自动进行这个转换,下面是关于转换的细节表:
内部类型 |
请求的类型 |
转换 |
NULL |
INTEGER |
结果是0 |
NULL |
FLOAT |
结果是0.0 |
NULL |
TEXT |
结果是NULL |
NULL |
BLOB |
结果是NULL |
INTEGER |
FLOAT |
从整形转换到浮点型 |
INTEGER |
TEXT |
整形的ASCII码显示 |
INTEGER |
BLOB |
同上 |
FLOAT |
INTEGER |
浮点型转换到整形 |
FLOAT |
TEXT |
浮点型的ASCII显示 |
FLOAT |
BLOB |
同上 |
TEXT |
INTEGER |
使用atoi() |
TEXT |
FLOAT |
使用atof() |
TEXT |
BLOB |
没有转换 |
BLOB |
INTEGER |
先到TEXT,然后使用atoi |
BLOB |
FLOAT |
先到TEXT,然后使用atof |
BLOB |
TEXT |
如果需要的话添加0终止符 |
备注:
BLOB数据类型是指二进制的数据块,比如要在数据库中存放一张图片,这张图片就会以二进制形式存放,在sqlite中对应的数据类型就是BLOB。
int sqlite3_column_bytes(sqlite3_stmt*, int iCol) int sqlite3_column_bytes16(sqlite3_stmt*, int iCol)
以上两个函数返回对应列的内容的字节数,这个字节数不包括后面类型转换过程中加上的0终止符。
下面是几个最安全和最简单的使用策略:
- 先sqlite3_column_text() ,然后 sqlite3_column_bytes()
- 先sqlite3_column_blob(),然后sqlite3_column_bytes()
- 先sqlite3_column_text16(),然后sqlite3_column_bytes16()
(1)得到数据行中某个列的数据:
sqlite3_column_xxx(sqlite3_stmt*, int iCol);
在sqlite3_step返回SQLITE_ROW后,使用它得到第iCol列的数据。
代表:
blob:指向保存数据内存的指针
bytes, bytes16: 得到该blob类型数据的大小,或者text转换为UTF8/UTF16的字符串长度。
double, int, int64: 数值
text,text16:字符串指针
type:该列的数据类型(SQLITE_INTEGER,SQLITE_FLOAT,SQLITE_TEXT,SQLITE_BLOB,SQLITE_NULL)
备注:
如果对该列使用了不同与该列本身类型适合的数据读取方法,得到的数值将是转换过的结果。
(2)得到数据行中某个列的数据的类型:
int sqlite3_column_type(sqlite3_stmt*, int iCol);
返回值:
SQLITE_INTEGER、SQLITE_FLOAT、SQLITE_TEXT、SQLITE_BLOB、SQLITE_NULL。
备注:
使用的方法和sqlite3_column_xxx()函数类似。
(3)获取列数:
int sqlite3_column_count(sqlite3_stmt *pStmt);
返回值:
如果过程没有返回值,如update,将返回0。
(4)获取列名
const char *sqlite3_column_name(sqlite3_stmt*,int);
(5)返回列数据类型
const char *sqlite3_column_decltype(sqlite3_stmt *, int i);
(6)得到当前行中包含的数据个数
int sqlite3_data_count(sqlite3_stmt *pStmt);
返回值:如果sqlite3_step返回SQLITE_ROW,可以得到列数,否则为零。
7.int sqlite3_reset(sqlite3_stmt *pStmt)
功能:
重置所有绑定的值,回到刚刚调用sqlite3_prepare后的状态。
8.int sqlite3_finalize(sqlite3_stmt *pStmt)
这个过程销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露。
在空指针上调用这个函数没有什么影响,同时可以准备语句的生命周期的任一时刻调用这个函数:在语句被执行前,一次或多次调用sqlite_reset之后,或者在sqlite3_step任何调用之后不管语句是否完成执行。
示例:
sqlite3_finalize(pStmt); pStmt = NULL;
9.sqlite3_close
这个过程关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放。
函数定义:
int sqlite3_close(sqlite3* pDB /* 由 sqlite3_open 或基相关的函数打开的 SQLite 对象句柄 */ );
说明:
该函数用来析构sqlite3对象。返回SQLITE_OK表示对象被成功析构,以及所有相关的资源被成功回收。
应用程序必须在关闭之前"完成(finalize)"所有的"预编译语句(prepared statements)",并且关闭所有的"二进制句柄绑定(BLOB handle)",如果在关闭时还有未完成的预编译语句或二进制句柄,那么函数返回SQLITE_BUSY(5)。
示例:
if(pDB != NULL) {sqlite3_close(pDB);pDB = NULL; }
10.sqlite3_exec
函数定义:
int sqlite3_exec(sqlite3* pDB, /* sqlite3句柄 */const char* sql, /* 被执行的 SQL 语句 */int (*callback)(void*,int,char**,char**), /* 执行/查询回调函数 */void* pvoid, /* 传递给回调函数的第一个参数 */char**errmsg /* 错误输出信息 */ );
说明:
该函数用来执行若干条SQL语句。
该函数包裹了先前版本的sqlite3_prepare()、sqlte3_step()和sqlite3_finalize()函数,这样用户就可以执行简单的代码执行多条SQL语句。
sqlite3_exec()接口执行多条以";"分隔的SQL语句。如果回调函数不为NULL,则它对每一个行查询结果都会调用该回调函数。如果没有回调函数被指定,sqlite3_exec()只是简单地忽略查询结果。
当在执行该SQL语句发生错误时,执行将发生中断,并且后面的语句也全部被忽略。如果errmsg参数不为空,任何错误信息将会被写进由sqlite3_malloc()得到的的内存空间中,即errmsg指向的内存。为了避免内存泄漏,应用程序应该在不需要该错误信息后立即调用sqlite3_free()释放该内存空间。如果errmsg参数不为NULL,并且没有错误发生,errmsg被设置为NULL。
如果回调函数返回非零,sqlite3_exec()立即中断查询,并且不再执行后续的SQL 语句,也不再调用回调函数,sqlite3_exec()将返回SQLITE_ABORT结束执行。
示例:
sqlite3_exec(pDB, to_utf8("delete from tablename where id=123;"), NULL, NULL, NULL); sqlite3_exec(pDB, to_utf8("create table if not exists tablename (id integer primary key,name text);"), NULL, NULL, NULL); sqlite3_exec(pDB, to_utf8("insert into tablename (name) values ('女孩不哭');"), NULL, NULL, NULL); if(sqlite3_exec(pDB, to_utf8("select * from tablename;"), sqlite_callback, NULL, &pszErrMsg) != SQLITE_OK) {...sqlite3_free(pszErrMsg);pszErrMsg = NULL; }
11.sqlite3_errcode
函数定义:
int sqlite3_errcode(sqlite3* pDB /* SQLite3 数据库句柄 */ );
说明:
该函数返回最近一次调用 sqlite3_ API时产生的错误码。
示例:
int errcode = sqlite3_errcode(pDB);
12.sqlite3_errmsg
函数定义:
const char *sqlite3_errmsg(sqlite3* pDB /* SQLite3 数据库句柄 */ );
说明:
该函数返回与pDB数据库指针相关的错误信息, 由英语书写。
用户不必考虑内存的释放,其由SQLite内部管理, 它也将会在下次调用函数时被覆盖。
示例:
printf("%s\n", sqlite3_errmsg(pDB));
13.sqlite3_key
函数定义:
int sqlite3_key(sqlite3 *db, /* Database to be rekeyed */const void *pKey, int nKey /* The key */ );
功能:
为加密的数据库指定密码,该函数在sqlite3_open之后调用。
14.sqlite3_rekey
函数定义:
int sqlite3_rekey(sqlite3 *db, /* Database to be rekeyed */const void *pKey, int nKey /* The new key */ );
功能:
重设数据库密码,如果pKey = 0或者nKey = 0,这数据库不加密。
15.sqlite3_get_table
函数定义:
int sqlite3_get_table(sqlite3*, /* An open database */const char *sql, /* SQL to be executed */char ***resultp, /* Result written to a char *[] that this points to */int *nrow, /* Number of result rows written here */int *ncolumn, /* Number of result columns written here */char **errmsg /* Error msg written here */ );
功能:
查询表。
参数说明:
PARAM1(IN):数据库句柄
PARAM2(IN):sql语句,以\0结尾
PARAM3(OUT):查询结果
PARAM4(OUT):返回行数(多少条数据)
PARAM5(OUT):返回列数(多少字段)
PARAM6(OUT):返回错误信息
返回值:
SQLITE_OK 成功。
16.sqlite3_free_table
函数定义:
void sqlite3_free_table(char **result);
功能:
释放通过sqlite3_get_table查询保存的结果数据。
参数说明:
PARAM1(IN):要释放的数据指针
17.sqlite3_create_function
函数定义:
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*) );
功能:
该函数用于注册/删除用户自定义函数。
18.其他
const char *sqlite3_libversion(void); int sqlite3_libversion_number(void); //功能:获取版本号 sqlite_int64 sqlite3_last_insert_rowid(sqlite3*); //功能:获取最后插入的行标示.int sqlite3_changes(sqlite3*); //功能:获取最近执行的sqlite3_exec影响的行数.int sqlite3_total_changes(sqlite3*); //功能:获取自从数据库打开后有改动的函数void sqlite3_interrupt(sqlite3*); //功能:打断或停止数据库当前操作.int sqlite3_complete(const char *sql); //功能:判断语句是否以分号(;)结尾int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); //功能:设置查询忙碌时的回调处理;说明:缺省的回调函数为空,如果回调函数为空,表锁定后sqlite3_exec()执行会直接返回SQLITE_BUSYint sqlite3_busy_timeout(sqlite3*, int ms); //功能:设置查询超时时间(毫秒)char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list); char *sqlite3_snprintf(int,char*,const char*, ...); //功能:格式化字符,需要用%q来代替%s.(主要是不用对分号'进行转义)void *sqlite3_malloc(int); void *sqlite3_realloc(void*, int); void sqlite3_free(void*); //功能:内存函数int sqlite3_set_authorizer(sqlite3*,int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),void *pUserData );//功能:设置数据库授权void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); void *sqlite3_profile(sqlite3*,void(*xProfile)(void*,const char*,sqlite_uint64), void*);void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); //功能:设置执行回调函数,sqlite3_exec(),sqlite3_step() ,sqlite3_get_table()时会调用void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); //功能:设置事务回调函数int sqlite3_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); //功能:获取错误码和错误消息int sqlite3_bind_parameter_count(sqlite3_stmt*); //功能:返回需要绑定的参数数目(sql语句中问号?数量)const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); //功能:获取绑定参数名字,?参数返回NULLint sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); //功能:获取绑定参数索引int sqlite3_clear_bindings(sqlite3_stmt*); //功能:清除绑定的参数
参考代码:
#include <stdio.h> #include "sqlite3.h" int main(){sqlite3 *db;char *zErrMsg = NULL;int rv;char szSql[128] = { 0 };sqlite3_stmt *stmt;rv = sqlite3_open("test.db", &db);if(rv){fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));sqlite3_close(db);return 1;}elsefprintf(stderr,"sqlite3_open OK\n");//这里查询时,假定数据库中存在表test,并且有一列为COL1(text类型)strcpy(szSql,"SELECT COL1 FROM test where COL1=?"); rv = sqlite3_prepare(db, szSql, 128, &stmt, NULL);if( rv != SQLITE_OK ) {fprintf(stderr, "sqlite3_prepare(%d): %s\n", rv, sqlite3_errmsg(db));return -1;} rv = sqlite3_bind_text(stmt, 1, "VALUE1", strlen("VALUE1"), SQLITE_STATIC);if( rv != SQLITE_OK ) {fprintf(stderr, "sqlite3_bind_text(%d): %s\n", rv, sqlite3_errmsg(db));return -1;}rv = sqlite3_step(stmt);if( (rv != SQLITE_OK) && (rv != SQLITE_DONE) && (rv != SQLITE_ROW) ) {fprintf(stderr, "sqlite3_step(%d): %s\n", rv, sqlite3_errmsg(db));return -1;}while( rv == SQLITE_ROW ){fprintf(stderr, "result: %s\n", sqlite3_column_text(stmt,0));rv = sqlite3_step(stmt);}rv = sqlite3_finalize(stmt);if( rv != SQLITE_OK ) {fprintf(stderr, "sqlite3_finalize(%d): %s\n", rv, sqlite3_errmsg(db));return -1;}sqlite3_close(db);return 0; } /****************************************************************************/ #include "stdafx.h" #include "sqlite3.h" static int callback( void*NotUsed,int argc, char **argv, char **azColName) {int i;for (i=0; i<argc; i++){printf ( "%s = %s/n", azColName[i], argv[i] ? argv[i] :"NULL" );}printf ( "/n" );return 0; } #define CHECK_RC(rc,szInfo,szErrMsg,db) if(rc!=SQLITE_OK) /{ printf ( "%s error!/n" ,szInfo);/printf ( "%s/n",szErrMsg); /sqlite3_free(szErrMsg); /sqlite3_close(db); /return 0;} int _tmain( int argc, _TCHAR* argv[]) {sqlite3 *db;char *dbPath= "f:/test.db";char *szErrMsg = 0;int rc= sqlite3_open(dbPath, &db);CHECK_RC(rc, "open database" ,db);char *szSql= "create table UserInfo(ID int primary key , UserName char, PassWord char);";rc=sqlite3_exec(db,szSql,0,0,&szErrMsg);CHECK_RC(rc, "create table" ,szErrMsg,db);rc=sqlite3_exec(db, "insert into UserInfo(ID,UserName,PassWord) values(1,'kfqcome','123456')",0,0,&szErrMsg);CHECK_RC(rc, "insert info" ,szErrMsg,db);rc=sqlite3_exec(db, "insert into UserInfo(ID,UserName,PassWord) values(2,'miss wang','654321')",0,0,&szErrMsg);CHECK_RC(rc, "insert info" ,szErrMsg,db);szSql= "select * from UserInfo" ;rc = sqlite3_exec(db,szSql, callback, 0, &szErrMsg);CHECK_RC(rc, "query values" ,szErrMsg,db);sqlite3_close(db);getchar ();return 0; }
输出结果:
ID = 1 UserName = kfqcome PassWord = 123456ID = 2 UserName = miss wang PassWord = 654321
程序示例
CREATE TABLE sqlite_master (type TEXT,name TEXT,tbl_name TEXT,rootpage INTEGER,sql TEXT );//获取Sqlite数据库中的表名和字段名 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"database_name"]; sqlite3 *database; sqlite3_open([path UTF8String], &database); charchar *errorMsg; const charchar *createSQL = "CREATE TABLE IF NOT EXISTS PEOPLE (ID INTEGER PRIMARY KEY AUTOINCREMENT, FIELD_DATA TEXT)"; int result = sqlite3_exec(database, createSQL, NULL, NULL, &errorMsg); sqlite3_stmt *statement; if (result == SQLITE_OK) { const charchar *getTableInfo = "select * from sqlite_master where type='table' order by name;"; result = sqlite3_prepare_v2(database, getTableInfo, -1, &statement, nil); while (sqlite3_step(statement) == SQLITE_ROW) { charchar *nameData = (charchar *)sqlite3_column_text(statement, 1); NSString *tableName = [[NSString alloc] initWithUTF8String:nameData]; NSLog(@"name:%@",tableName); } const charchar *getColumn = "PRAGMA table_info(PEOPLE)"; result = sqlite3_prepare_v2(database, getColumn, -1, &statement, nil); while (sqlite3_step(statement) == SQLITE_ROW) { charchar *nameData = (charchar *)sqlite3_column_text(statement, 1); NSString *columnName = [[NSString alloc] initWithUTF8String:nameData]; NSLog(@"columnName:%@",columnName); } sqlite3_finalize(statement); } sqlite3_close(database);
转载于:https://www.cnblogs.com/YSPXIZHEN/p/5816532.html
SQLite剖析之编程接口详解相关推荐
- predicate java 作用_Java函数式编程接口详解之Predicate
一.初识 Predicate是Java提供的重要的函数编程接口之一,作用主要是用于逻辑判断. 首先看看源码: @FunctionalInterface public interface Predica ...
- 【java8新特性】——lambda表达式与函数式接口详解(一)
一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...
- mfc编程vc6.0实现进程的创建和通信_免费送书:windows黑客编程技术详解
01 书怎么送 点赞并留言,关注在下面的公众号后台回复「抽奖」,弹出小程序后点击参与. 开奖时间是 7 月 7 号 20:00 ,一定要留意微信消息,如果你中奖了,请尽快在中奖页面提交收件人信息并备注 ...
- linux命令大全 美pdf,Linux编程命令详解_10331298_(美)Richard..pdf-得力文库
Linux编程命令详解_10331298_(美)Richard....pdf General Ination 书名Linux编程命令详解 作者(美)Richard Petersen著:梁普选,刘玉芬等 ...
- 【JavaWeb】Servlet系列——HttpServletRequest接口详解
文章目录 23 HttpServletRequest接口详解 23.1 关于HttpServletRequest接口 23.2 HttpServletRequest接口的实现类谁写的? HttpSer ...
- 看完之后保证你对socket编程步骤胸有成竹。 C++ Socket网络编程基础详解(TCP)
C++ Socket网络编程基础详解(TCP版) 网络编程,就是编写程序使得两台计算机交换数据,其实从本质上来讲,网络编程最终所实现的功能,和我们文件的输入输出很相似,只是文件输入输出的对象 ...
- 百家号 python高手养成_【一点资讯】Python使用PyQt5进行图形界面GUI编程之详解QWidget类的坐标体系 www.yidianzixun.com...
Python使用PyQt5进行图形界面GUI编程之详解QWidget类的坐标体系 上篇内容,我们详细介绍了使用PyCharm中LiveTemplate功能快速输入一个GUI应用框架的办法.(参见学会这 ...
- Python的C语言接口 - 详解官方文档
Python的C语言接口 - 详解官方文档 索引 Python的C语言接口 - 详解官方文档 介绍 / Introduce 代码标准 / Coding Standards 包含文件 / Include ...
- Java6.0中Comparable接口与Comparator接口详解
Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...
最新文章
- 如何将零终止的字节数组转换为字符串?
- selinux 的管理
- python知识点1
- python3重写new方法_Python 3.8 新功能一览
- 机器学习实战3-sklearn使用下载MNIST数据集进行分类项目
- 微课|中学生可以这样学Python(例11.2):tkinter猜数游戏(3)
- 使用SharedPreference保存用户数据的步骤
- jstl有什么优势(简单介绍)
- 【9933】单词的划分
- 手动方式安装 eclipse 的svn插件 Subversive和 Subversive SVN Connectors
- 图片像素、大小、分辨率的关系
- html 警告图标,HTML+CSS入门 CSS实现核辐射警告标志
- 企业如何搭建商业智能BI,过程中又需要注意哪些事项
- Failed to build sentencepiece
- 从输入url到页面返回到底发生了什么
- [论文阅读:姿态识别Transformer] TransPose: Keypoint Localization via Transformer 2021 ICCV
- 工资高的互联网工作者都在干什么
- Mybatis的Spring集成、Aop整合
- 什么是中台?企业为什么要建中台?从数据中台到AI中台。
- python爬虫爬取彼岸图网图片