sqlite3_open_v2
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 */
)
参数1:sqlite数据库文件名;
参数2:输出参数,数据库句柄;
参数3:标志,如下:
/* Ok for sqlite3_open_v2() 只读模式打开,若数据库不存在,则返回错误*/
#define SQLITE_OPEN_READONLY 0x00000001
/* Ok for sqlite3_open_v2() 若可能,将打开数据库进行读写,或仅在文件受操作系统写保护时才进行读取;这两种情况下数据库必须依据存在,否则返回错误;*/
#define SQLITE_OPEN_READWRITE 0x00000002
/* Ok for sqlite3_open_v2() 数据库不存则创建*/
#define SQLITE_OPEN_CREATE 0x00000004
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
/* Ok for sqlite3_open_v2() 若设置了此标志,则文件名可解释成URL */
#define SQLITE_OPEN_URI 0x00000040
/* Ok for sqlite3_open_v2() 数据库将作为内存数据库打开;*/
#define SQLITE_OPEN_MEMORY 0x00000080
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
/* Ok for sqlite3_open_v2() 新的数据库连接将使用"多线程模式".意味着运行单独的线程同时使用SQLite,只要每个线程使用不同数据库连接;*/
#define SQLITE_OPEN_NOMUTEX 0x00008000
/* Ok for sqlite3_open_v2() 新的数据库将使用"序列化"线程模式;意味多个线程可以安全的尝试同时使用同一数据库连接;*/
#define SQLITE_OPEN_FULLMUTEX 0x00010000
/* Ok for sqlite3_open_v2() 数据库已启用共享缓存;*/
#define SQLITE_OPEN_SHAREDCACHE 0x00020000
/* Ok for sqlite3_open_v2() 数据库被打开共享缓存禁用;*/
#define SQLITE_OPEN_PRIVATECACHE 0x00040000
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
参数4:sqlite3_vfs对象的名称,该对象定义了新数据库连接应该使用的操作系统接口; NULL表示使用默认的sqlite3_vfs对象;
sqlite3_prepare_v2
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
)
首选sqlite3_prepare_v2( ); sqlite3_prepare( )接口是遗留的,应该避免; sqlite3_prepare_v3( )有一个二外的"prepFlags"选项,用于特殊用途;
参数1:sqlite3_open_v2等获取的数据句柄;
参数2:utf8编码格式的sql语句;
参数3:nBytes<0,则zSql被读取到第一个零终止符; nBytes=0,不会生成任何准备好的语句;nBytes>0,表示从zSql语句读取的字节数;
参数4:ppStmt指向一个编译好的准备好的语句,可以使用sqlite3_step()执行; 若参数2输入的文本不包含SQL(输入的是空字符串或注释),则*ppStmt设置为NULL; 调用过程负责在编译完成后使用sqlite3_finalize()删除已编译的SQL语句;
返回值:指向成功返回SQLITE_OK;
sqlite3_bind_xxx
将值绑定到准备好的语句
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, sqlite3_int64);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
参数1: 由sqlite3_prepare_v2()返回的sqlite3_stmt对象的指针;
参数2: 要设置的sql参数的索引;最左的sql参数的索引为1;当多次使用同一个命名的sql参数时,第二次和后续出现的索引与第一次出现的索引相同; 填1即可;
参数3: 要绑定到参数的值;若上述有该参数的是NULL指针,则忽略参数4;结果与sqlite3_bind_null相同;
参数4: 是参数3的字节数(字节而不是字符)
参数5:指示或控制参数3引用的对象的生存期; (1)可以传递一个析构函数,在sqlite处理完blob或字符串后处理它;即使对绑定API的调用失败,也会调用该函数来处理blob或字符串,但若参数3为NULL指针或参数4为负数,则不会调用析构函数; (2)可以传递常量SQLITE_STATIC,以知识应用程序任然负责处理对象;这种情况下,对象及其提供的指针必须保持有效,直到完成准备好的语句或将同一sql参数绑定到其他对象; (3)可以传递常量SQLITE_TRANSENT,以指示从sqlite3_bind_* 返回之前复制对象;
返回值: 成功返回SQLITE_OK;
sqlite3_step
int sqlite3_step(sqlite3_stmt*);
在使用了sqlite3_prepare_v2()等准备好语句后,必须调用一次或多次该函数来评估sqlite语句;
SQLITE_DONE表示语句已经成功执行完毕;
sqlite3_finalize
int sqlite3_finalize(sqlite3_stmt *pStmt);
调用sqlite3_finalize()函数以删除准备好的语句;
若最近换一次求值没有遇到错误,或者从未对语句求值 ,则sqlite3_finalize()返回SQLITE_OK;
6. 返回错误码
如果字符串或BLOB的大小超过sqlite3_limit(SQLITE_limit_LENGTH)或SQLITE_MAX_LENGTH所施加的限制,则可能返回SQLITE_TOOBIG。
如果参数索引超出范围,则返回SQLITE_RANGE。
如果malloc()失败,则返回SQLITE_NOMEM。
7. 查询相关API
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); double sqlite3_column_double(sqlite3_stmt*, int iCol); int sqlite3_column_int(sqlite3_stmt*, int iCol); const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); int sqlite3_column_bytes(sqlite3_stmt*, int iCol); int sqlite3_column_type(sqlite3_stmt*, int iCol);
上述例程返回有关查询的当前结果行的当个列的信息; 在每一种情况下,第一个参数都是一个sqlite3_stmt指针,由sqlite3_prepare_v2()获取; 第二个参数是返回其列的索引,结果最左侧的列的索引为0; 可以由sqlite3_column_count()确定结果中的列数;
若SQL语句当前未指向有效行,或者列索引超出范围,则结果未定义;只有在最近一次对sqlite3_step()的调用返回SQLITE_ROW并且既没有调用sqlite3_reset(),也没有调用sqlite3_finalize()时,才调用这些例程;
sqlite3_column_type()返回结果列的初始数据类型的数据类型代码;值是SQLITE_INTEGER、SQLITE_FLOAT、SQLITE_TEXT、SQLITE_BLOB或SQLITE_NULL之一;
若结果是BLOB或utf-8字符串,则sqlite3_column_bytes()接口来确定该BLOB或字符串的大小;返回的值是字符串的字节数而不是字符数;
8. 示例
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
// 一条速度 信息
struct dr_speed_t
{
time_t start_time; // 时间
unsigned char speed; // 平均速度
unsigned char state; // 状态信息
unsigned char reserved[2];
};
static sqlite3 *g_db = NULL;
//typedef int (*sqlite3_callback)(void*,int,char**, char**);
static int count_callback(void *args, int nCol, char **rowArr, char **colName)
{
int *total_size = (int *)args;
*total_size = atoi(*rowArr);
return 0;
}
static int create_callback(void *args, int nCol, char **rowArr, char **colName)
{
sqlite3 *db = (sqlite3 *)args;
printf("nCol = %d %s \n",nCol, rowArr[0]);
if(atoi(rowArr[0]) < 1){
char sql[128], *err;
int ret;
snprintf(sql, sizeof(sql), "create table %s(tim INTEGER primary key, type INTEGER, bval blob)", "tab_product");
ret = sqlite3_exec(db, sql, 0, 0, &err);
if(ret != SQLITE_OK){
if(err){
sqlite3_free(err);
return -1;
}
}
}
return 0;
}
int SqlSave(time_t tim, void *extData, int dataLen)
{
char sql[128] = {0};
char *err = NULL;
int ret ;
sqlite3_stmt *stmt = NULL;
snprintf(sql, sizeof(sql),"replace into %s(tim,type,bval) values(%ld,%d,?)","tab_product",tim,0);
ret = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
if(ret != SQLITE_OK){
printf("sqlite3_prepare_v2 err\n");
return -1;
}
ret = sqlite3_bind_blob(stmt, 1, extData, dataLen, NULL);
if(ret != SQLITE_OK){
goto ERR;
}
ret = sqlite3_step(stmt);
if(ret != SQLITE_OK){
goto ERR;
}
sqlite3_finalize(stmt);
return 0;
ERR:
sqlite3_finalize(stmt);
return -1;
}
int SqlQueryCount(time_t start_time, time_t end_time)
{
char sql[256], *err;
int ret;
int total_size = 0;
snprintf(sql, sizeof(sql), "select count(*) from %s where tim >= %ld and tim < %ld", "tab_product", start_time, end_time);
ret = sqlite3_exec(g_db, sql, count_callback, &total_size, &err);
if(ret != SQLITE_OK){
printf("sqlite3_exec err\n");
return -1;
}
return total_size;
}
int SqlQuerySpeed(time_t start_time, time_t end_time)
{
char sql[128] = {0};
char *err = NULL;
int ret ;
printf("query count = %d\n",SqlQueryCount(start_time, end_time));
sqlite3_stmt *stmt = NULL;
snprintf(sql, sizeof(sql),"select * from %s where tim > %ld and tim < %ld order by tim desc","tab_product",start_time, end_time);
ret = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
if(ret != SQLITE_OK){
printf("sqlite3_prepare_v2 err\n");
return -1;
}
while(1)
{
ret = sqlite3_step(stmt);
if(ret != SQLITE_ROW){
printf("query exit\n");
break;
}
time_t tim = sqlite3_column_int(stmt, 0);
int type = sqlite3_column_int(stmt, 1);
struct dr_speed_t *speed = (struct dr_speed_t *)sqlite3_column_blob(stmt, 2);
int blob_len = sqlite3_column_bytes(stmt, 2);
if(blob_len != sizeof(struct dr_speed_t)){
printf("--> query err\n");
}
printf("speed=%d time=%ld state=%d\n",speed->speed,speed->start_time,speed->state);
}
sqlite3_finalize(stmt);
return 0;
}
int main(int argc, const char *argv[])
{
char sql[128] = {0};
char *err = NULL;
int ret ;
//读写,不存在则创建,多线程访问;
ret = sqlite3_open_v2("./config.db", &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_FULLMUTEX, NULL);
if(ret != SQLITE_OK){
printf("sqlite_open_v2 err\n");
return -1;
}
//检查数据表是否存在,不存在回调里创建
snprintf(sql,sizeof(sql),"select count(*) from sqlite_master where type='table' and name='%s'","tab_product");
ret = sqlite3_exec(g_db, sql, create_callback, g_db, &err);
if(ret != SQLITE_OK){
sqlite3_free(err);
sqlite3_close_v2(g_db);
}
//保存100次数据,正常情况下单次保存;
struct dr_speed_t speed;
time_t t = time(NULL);
for(int i = 0; i < 100; ++i){
memset(&speed, 0, sizeof(struct dr_speed_t));
speed.speed = i;
speed.start_time = t/1000 + i;
speed.state = ((i % 2) == 0) ? 0 : 1;
SqlSave(speed.start_time,&speed,sizeof(struct dr_speed_t));
}
sleep(1);
//批量查询
SqlQuerySpeed(0, time(NULL));
sqlite3_close_v2(g_db);
return 0;
}