1.什么是BLOB数据

BLOB (binary large object)即二进制大对象,是一种可以存储二进制文件的容器。在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。常见的BLOB文件有图片、声音和自定义对象等。

2.BLOB操作相关API介绍

2.1 准备SQL语句

  • 函数原型
int sqlite3_prepare(
  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 */
);
  • 参数列表
    sqlite3 *db —- 数据库操作句柄,由sqlite3_open()函数得到
    const char *zSql —- SQL语句
    int nByte —- sql语句的长度
    sqlite3_stmt **ppStmt —- 编译好的准备语句指针,该指针可以由sqlite3_step()执行;如果函数发生错误,该指针为NULL
    const char **pzTail —- 当生成的指定语句超过nByte指定的长度时,剩余的语句存放位置。建议zSql和nByte设置足够长,这样该参数就可以直接置为NULL
  • 返回值
    int —- 函数执行成功时,返回SQLITE_OK;否则返回错误码

2.2 BLOB绑定函数

  • 函数原型
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
    int —- 要绑定的BLOB下标,从1开始
    const void* —- BLOB数据的指针
    int n —- BLOB数据长度
    void()(void) —- 析构回调函数,一般默认为空
  • 返回值
    int —- 函数执行成功时,返回SQLITE_OK;否则返回错误码

2.3 准备语句执行函数

  • 函数原型
int sqlite3_step(sqlite3_stmt*);
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
  • 返回值
    int —- 函数执行成功时,返回SQLITE_OK;否则返回错误码

2.4 销毁准备语句函数

  • 函数原型
 int sqlite3_finalize(sqlite3_stmt *pStmt);
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
  • 返回值
    int —- 函数执行成功时,返回SQLITE_OK;否则返回错误码

2.5 获取指定字段的整形数据值

  • 函数原型
int sqlite3_column_int(sqlite3_stmt*, int iCol);
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
    int iCol —- 列的编号,从0开始
  • 返回值
    int —- 函数执行成功时,返回SQLITE_OK;否则返回错误码

2.6 获取指定字段的BLOB值

  • 函数原型
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
    int iCol —- 列的编号,从0开始
  • 返回值
    const void * —- BLOB数据指针

2.7 获取指定BLOB数据长度

  • 函数原型
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
  • 参数列表
    sqlite3_stmt* —- 准备语句指针,该指针有sqlite3_prepare()函数得到
    int iCol —- BLOB下标,从1开始
  • 返回值
    int —- BLOB数据长度

3.代码实例

  • 代码说明
    本例主要演示如何插入和查询自定义对象。
  • 测试平台
    1.开发语言:C++
    2.开发工具:VS2015
    3.操作系统:Win7 X64
  • 测试数据说明
    测试表为Student_Blob表,其基本结构如下:
    这里写图片描述

  • 具体代码

#include <iostream>
#include <Windows.h>
using namespace std;

//sqlite3头文件
#include "sqlite3.h"
//sqlite3库文件
#pragma comment(lib,"sqlite3.lib")

//函数功能:将utf8字符转gb2312字符
//参数:    const char* utf8[IN]                   -- UTF8字符
//返回值:  char*                                  -- gb2312字符
char* U2G(const char* utf8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    if (wstr) delete[] wstr;
    return str;
}

//unicode字符转utf8
//函数功能:将gb2312字符转换为utf8字符
//参数:    const char* gb2312[IN]                   -- gb2312字符
//返回值:  char*                                    -- UTF8字符
char* G2U(const char* gb2312)
{
    int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
    len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
    if (wstr) delete[] wstr;
    return str;
}

//测试学生数据结构体
typedef struct TestStudent
{
    char name[20];               //姓名
    int age;                     //年龄            
};

//函数功能:向表中插入BLOB数据
//参数:    sqlite3 *db[IN]                               -- 数据库操作指针
//          const TestInfoStruct* info[IN]                -- 要插入的信息
//          const int recordId[IN]                        -- 记录ID
//返回值:  bool                                          -- 函数执行成功,则返回true;否则返回false
bool InsertBlobData(sqlite3 *db, const TestStudent student,const int recordId)
{
    char *zErrMsg = 0;
    char sql[1000];
    int rc;

    sqlite3_stmt *stmt;                                           
    sprintf_s(sql, "insert into Student_Blob values('%d',?);", recordId);
    sqlite3_prepare(db, sql, strlen(sql), &stmt, 0);                  
    {
        sqlite3_bind_blob(stmt, 1, &student, sizeof(TestStudent), NULL);   
        sqlite3_step(stmt);                                             
    }

    sqlite3_finalize(stmt);
    return true;
}


//函数功能:向表中插入BLOB数据
//参数:    sqlite3 *db[IN]                         -- 数据库操作指针
//          TestInfoStruct* info[IN]                -- 要插入的信息
//返回值:  bool                                    -- 函数执行成功,则返回true;否则返回false
bool SelectBlobData(sqlite3 *db)
{
    char *zErrMsg = 0;
    char sql[1000];
    int rc;

    sqlite3_stmt *stmt;    
    //读取数据
    sqlite3_prepare(db, "select * from Student_Blob;", strlen("select * from Student_Blob;"), &stmt, 0);
    int result = sqlite3_step(stmt);
    int id = 0, len = 0;
    while (result == SQLITE_ROW)                                 
    {
        char cStudentId[20];
        TestStudent tempStudent;
        cout << endl<<"查询到一条记录" << endl;
        id= sqlite3_column_int(stmt, 0);
        cout << "记录编号:" << id << endl;
        const void * pReadBolbData = sqlite3_column_blob(stmt, 1);      
        len = sqlite3_column_bytes(stmt, 1);                                                                             

        memcpy(&tempStudent, pReadBolbData, len);                      
        cout << "姓名=" << tempStudent.name << endl;
        cout << "年龄=" << tempStudent.age << endl;
        result = sqlite3_step(stmt);
    }
    sqlite3_finalize(stmt);                                        
    return true;
}


int main()
{
    //操作数据库
    sqlite3 *db;
    char *zErrMsg = 0;
    char sql[1000];
    sqlite3 *pDataBase = NULL;

    //打开数据库
    //如果路径不含中文,可以不用转码。不过保险起见,建议全部转码。
    int iRet = sqlite3_open(G2U("E:\\sqlite数据库\\testSQLite.db"), &pDataBase);
    if (iRet)
    {
        cout << "数据库打开失败,失败原因:" << sqlite3_errmsg(pDataBase) << endl;
    }
    else
    {
        cout << "数据库打开成功!" << endl;

        //写BLOB数据
        TestStudent student1;
        sprintf_s(student1.name, "张三");
        student1.age = 19;
        InsertBlobData(pDataBase,student1,1);

        TestStudent student2;
        sprintf_s(student2.name, "李四");
        student2.age = 18;
        InsertBlobData(pDataBase, student2,2);

        //读取数据
        SelectBlobData(pDataBase);

        //关闭数据库
        iRet = sqlite3_close(pDataBase);
        if (0 == iRet)
        {
            cout << "数据库关闭成功!" << endl;
        }
    }

    getchar();
    return 0;
}
  • 输出结果
    这里写图片描述

栏目导航
上一篇:SQLite学习笔记(七)– 数据插入、更新和删除(C++实现)
下一篇:SQLite学习笔记(九)– 视图的定义与删除(C++实现)

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐