sqlite3简单实例

/*  
 * File:   sqlite_test.cpp 
 * Author: Carl 
 * 
 * Created on September 20, 2012, 3:28 PM 
 */  

#include <cstdlib>  
#include <cstdio>  
#include <sqlite3.h>  

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)  
{  
    int i = 0;  

    printf("notused:0x%x, argc:%d\n", notused, argc);  
    for (i = 0; i < argc; i++)  
    {  
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);  
    }  
    printf("\n");  

    return 0;  
}  

/* 
 *  
 */  
int main(int argc, char** argv)  
{  
    const char *sSQL1 = "create table users(userid varchar(20) PRIMARY KEY, age int, birthday datetime);";  
    const char *sSQL2 = "insert into users values('wang', 20, '1989-5-4');";  
    const char *sSQL3 = "select * from users;";  

    sqlite3 *db = 0;  
    char *pErrMsg = 0;  
    int ret = 0;  

    //连接数据库  
    ret = sqlite3_open("./test.db", &db);  
    if (ret != SQLITE_OK)  
    {  
        fprintf(stderr, "无法打开数据库:%s\n", sqlite3_errmsg(db));  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库连接成功\n");  

    //执行建表SQL  
    ret = sqlite3_exec(db, sSQL1, _sql_callback, 0, &pErrMsg);  
    if (ret != SQLITE_OK)  
    {  
        fprintf(stderr, "SQL create error: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg); //这个要的哦,要不然会内存泄露的哦!!!  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库建表成功!!\n");  

    //执行插入数据  
    ret = sqlite3_exec(db, sSQL2, _sql_callback, 0, &pErrMsg);  
    if (ret != SQLITE_OK)  
    {  
        fprintf(stderr, "SQL insert error: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg); //这个要的哦,要不然会内存泄露的哦!!!  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库插入数据成功!\n");  

    //执行查询操作  
    ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);  
    if (ret != SQLITE_OK)  
    {  
        fprintf(stderr, "SQL error: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg);  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库查询成功!!\n");  

    //关闭数据库  
    sqlite3_close(db);  
    db = 0;  

    return 0;  
}  

结果:

[carl@Fedora sqlite]$ g++ sqlite_test.cpp -lsqlite3  
[carl@Fedora sqlite]$ ./a.out   
数据库连接成功  
数据库建表成功!!  
数据库插入数据成功!  
notused:0x0, argc:3  
userid = wang  
age = 20  
birthday = 1989-5-4  

数据库查询成功!!  
[carl@Fedora sqlite]$ 

事务实现:

/*  
 * File:   sqlite_test.cpp 
 * Author: Carl 
 * 
 * Created on 2012年9月22日, 上午7:50 
 */  

#include <cstdlib>  
#include <cstdio>  
#include <sqlite3.h>  

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)  
{  
    int i = 0;  

    printf("notused:0x%x, argc:%d\n", notused, argc);  
    for (i = 0; i < argc; i++)  
    {  
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);  
    }  
    printf("\n");  

    return 0;  
}  


/* 
 *  
 */  
int main(int argc, char** argv)  
{  
    const char *sSQL1 = "create table test_for_cpp (id int, name varchar(10), age int);";  
    char sql[100] = {0};  
    sqlite3 *db = NULL;  
    char *pErrMsg = NULL;  
    int ret = 0;  
    bool is_success = true;  
    const char *sSQL3 = "select * from test_for_cpp;";    

    ret = sqlite3_open("./test.db", &db);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库连接成功\n");    

    ret = sqlite3_exec(db, sSQL1, NULL, 0, &pErrMsg);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "SQL create error: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg);  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库建表成功!!\n");    

    sqlite3_exec(db, "begin;", _sql_callback, 0, &pErrMsg); //开启事务  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "SQL begin error: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg);  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库开启事务成功!!\n");    

    for (int i = 0; i < 10; i++)  
    {  
        sprintf(sql, "insert into test_for_cpp(id, name, age) values(%d, \"%s\", %d);", i, "Carl", i);  
        ret = sqlite3_exec(db, sql, _sql_callback, 0, &pErrMsg);  
        if (SQLITE_OK != ret)  
        {  
            is_success = false;  
            fprintf(stderr, "for %d time error: %s\n", i, pErrMsg);  
            sqlite3_free(pErrMsg);  
            break;  
        }  
    }  

    if (is_success)  
    {  
        sqlite3_exec(db, "commit;", 0, 0, 0);  
        printf("数据库插入数据成功!\n");    
    }  
    else  
    {  
        sqlite3_exec(db, "rollback;", 0, 0, 0);  
        printf("数据库插入数据失败!\n");    
    }  

    ret = sqlite3_exec(db, sSQL3, _sql_callback, 0, &pErrMsg);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "SQL ERROR: %s\n", pErrMsg);  
        sqlite3_free(pErrMsg);  
        sqlite3_close(db);  
        return 1;  
    }  
    printf("数据库查询成功!!\n");    

    sqlite3_close(db);  
    db = 0;  

    return 0;  
}  
[carl@Fedora sqlite]$ g++ sqlite_test.cpp -lsqlite3  
[carl@Fedora sqlite]$ ./a.out   
数据库连接成功  
数据库建表成功!!  
数据库开启事务成功!!  
数据库插入数据成功!  
notused:0x0, argc:3  
id = 0  
name = Carl  
age = 0  

notused:0x0, argc:3  
id = 1  
name = Carl  
age = 1  

notused:0x0, argc:3  
id = 2  
name = Carl  
age = 2  

notused:0x0, argc:3  
id = 3  
name = Carl  
age = 3  

notused:0x0, argc:3  
id = 4  
name = Carl  
age = 4  

notused:0x0, argc:3  
id = 5  
name = Carl  
age = 5  

notused:0x0, argc:3  
id = 6  
name = Carl  
age = 6  

notused:0x0, argc:3  
id = 7  
name = Carl  
age = 7  

notused:0x0, argc:3  
id = 8  
name = Carl  
age = 8  

notused:0x0, argc:3  
id = 9  
name = Carl  
age = 9  

数据库查询成功!!  
[carl@Fedora sqlite]$ 

接口应用:

/*  
 * File:   sqlite_test2.cpp 
 * Author: Carl 
 * 
 * Created on September 21, 2012, 3:12 PM 
 */  

#include <cstdlib>  
#include <cstdio>  
#include <cstring>  
#include <sqlite3.h>  

static int _sql_callback(void *notused, int argc, char **argv, char **szColName)  
{  
    int i = 0;  

    printf("notused:0x%x, argc:%d\n", notused, argc);  
    for (i = 0; i < argc; i++)  
    {  
        printf("%s = %s\n", szColName[i], argv[i] == 0 ? "NULL" : argv[i]);  
    }  
    printf("\n");  

    return 0;  
}  

/* 
 *  
 */  
int main(int argc, char** argv)  
{  
    sqlite3 *conn = NULL;  
    sqlite3_stmt *stmt = NULL;  
    char *err_msg = NULL;  
    int ret = 0;  

    char col_types[][10] = {"", "Interger", "Float", "Text", "Blob", "NULL"};  

    ret = sqlite3_open("./test.db", &conn);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "sqlite open err, %d\n", ret);  
        return 1;  
    }  
    printf("打开数据库成功!!!\n");  

//    ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==:name", -1, &stmt, (const char **)&err_msg);  
    ret = sqlite3_prepare_v2(conn, "SELECT * FROM [test_for_cpp] WHERE [name]==?2", -1, &stmt, (const char **)&err_msg);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "sqlite prepare error: %s\n", err_msg);  
        sqlite3_free(err_msg);  
        sqlite3_close(conn);  
        return 1;  
    }  
//    printf("数据库语句对象编译成功!!!%d\n", sqlite3_bind_parameter_index(stmt, ":name"));  
    printf("数据库语句对象编译成功!!!\n");  

    ret = sqlite3_bind_text(stmt, 2, "Carl", 4, SQLITE_STATIC);  
    if (SQLITE_OK != ret)  
    {  
        fprintf(stderr, "sqlite bind error: %d\n", ret);  
        sqlite3_close(conn);  
        return 1;  
    }  
    printf("数据库语句对象bind成功!!!\n");  

    while (ret = sqlite3_step(stmt), ret == SQLITE_ROW)  
    {  
        int col_count = sqlite3_column_count(stmt); //结果集中列的数量  
        printf("列数:%d\t", col_count);  
        const char *col_0_name = sqlite3_column_name(stmt, 0); //获取列名  
        printf("列名:%s\t", col_0_name);  
        int id = sqlite3_column_int(stmt, 0);  
        printf("id值:%d\t", id);  
        int id_type = sqlite3_column_type(stmt, 0); //获取列数据类型  
        printf("id类型:%d\t", id_type);  

        const char *col_2_name = sqlite3_column_name(stmt, 2);  
        int age = sqlite3_column_int(stmt, 2);  
        int age_type = sqlite3_column_type(stmt, 2);  

        const char *col_1_name = sqlite3_column_name(stmt, 1);  
        char name[80];  
        strncpy(name, (const char *)sqlite3_column_text(stmt, 1), 80);  
        int name_type = sqlite3_column_type(stmt, 1);  

        //打印结果  
        printf("col_count: %d, %s = %d(%s), %s = %s(%s), %s = %d(%s)\n",   
               col_count, col_0_name, id, col_types[id_type], col_1_name, name,  
               col_types[name_type], col_2_name, age, col_types[age_type]);  
    }  

    fprintf(stderr, "sqlite step exit with %d\n", ret);  
    sqlite3_finalize(stmt);  
    sqlite3_close(conn);  

    return 0;  
}  
[carl@Fedora sqlite]$ g++ sqlite_test2.cpp -lsqlite3  
[carl@Fedora sqlite]$ ./a.out   
打开数据库成功!!!  
数据库语句对象编译成功!!!  
数据库语句对象bind成功!!!  
列数:3    列名:id   id值:0   id类型:1  col_count: 3, id = 0(Interger), name = Carl(Text), age = 0(Interger)  
列数:3    列名:id   id值:1   id类型:1  col_count: 3, id = 1(Interger), name = Carl(Text), age = 1(Interger)  
列数:3    列名:id   id值:2   id类型:1  col_count: 3, id = 2(Interger), name = Carl(Text), age = 2(Interger)  
列数:3    列名:id   id值:3   id类型:1  col_count: 3, id = 3(Interger), name = Carl(Text), age = 3(Interger)  
列数:3    列名:id   id值:4   id类型:1  col_count: 3, id = 4(Interger), name = Carl(Text), age = 4(Interger)  
列数:3    列名:id   id值:5   id类型:1  col_count: 3, id = 5(Interger), name = Carl(Text), age = 5(Interger)  
列数:3    列名:id   id值:6   id类型:1  col_count: 3, id = 6(Interger), name = Carl(Text), age = 6(Interger)  
列数:3    列名:id   id值:7   id类型:1  col_count: 3, id = 7(Interger), name = Carl(Text), age = 7(Interger)  
列数:3    列名:id   id值:8   id类型:1  col_count: 3, id = 8(Interger), name = Carl(Text), age = 8(Interger)  
列数:3    列名:id   id值:9   id类型:1  col_count: 3, id = 9(Interger), name = Carl(Text), age = 9(Interger)  
sqlite step exit with 101 //101意思为SQLITE_DONE  
[carl@Fedora sqlite]$   

*(1) 使用“语句参数”方式,具有更高的安全性,可以有效防止“SQL注入攻击”。 “SQL注入攻击”要想达到目的,就必须让attack value随着SQL命令字符串一起传送进SQL解析器。黑客如果在一条SQL命令字符串被送入到sqlite3_prepare函数之前,利用c字符串处理函数等途径将attack value注入其中,而在sqlite3_prepare函数之中进行解析(parse),就可以达到攻击目的。而使用“语句参数”方式,被传送到sqlite3_prepare函数的只是SQL命令字符串中的参数符号(如:“?”),而不是具体的值。在sqlite3_prepare函数执行之后,才会使用bind函数给参数符号绑定具体的值,这就可以避免attack value随着SQL命令字符串一起在sqlite3_prepare函数中被解析,从而有效躲避“SQL注入攻击”。
(2)使用“语句参数”方式,可以更快的完成值替换。
(3)使用“语句参数”方式,更节省内存。原因是使用如snprintf函数,需要一个SQL命令模板,一块足够大的输出缓存,而且字符串处理函数需要工作内存(working memory),除此之外对于整形,浮点型,特别是BLOBs,经常会占用更多的空间。*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值