sqlite3数据库高效API(六)

  1. 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对象;

  1. 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;

  1. 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;

  1. sqlite3_step
int sqlite3_step(sqlite3_stmt*);

在使用了sqlite3_prepare_v2()等准备好语句后,必须调用一次或多次该函数来评估sqlite语句;

SQLITE_DONE表示语句已经成功执行完毕;

  1. 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值