文档章节

sqlite3中BLOB数据类型存储大对象运用示例

涩女郎
 涩女郎
发布于 2015/08/26 21:29
字数 1997
阅读 958
收藏 5

1:常用接口

个人比较喜欢sqlite, 使用最方便,唯一的准备工作是下载250K的源;而且作者很热心,有问必答。

以下演示一下使用sqlite的步骤,先创建一个数据库,然后查询其中的内容。2个重要结构体和5个主要函数:

sqlite3               *pdb, 数据库句柄,跟文件句柄FILE很类似

sqlite3_stmt      *stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句

 

sqlite3_open(),   打开数据库

sqlite3_exec(),   执行非查询的sql语句

sqlite3_prepare(), 准备sql语句,执行select语句或者要使用parameter bind时,用这个函数(封装了sqlite3_exec).

Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动。

Sqlite3_close(), 关闭数据库文件

 

还有一系列的函数,用于从记录集字段中获取数据,如

sqlite3_column_text(), 取text类型的数据。

sqlite3_column_blob(),取blob类型的数据

sqlite3_column_int(), 取int类型的数据

2:sqlite数据类型介绍

     在进行数据库Sql操作之前,首先有个问题需要说明,就是Sqlite的数据类型,和其他的数据库不同,Sqlite支持的数据类型有他自己的特色,这个特色有时会被认为是一个潜在的缺点,但是这个问题并不在我们的讨论范围之内。
大多数的数据库在数据类型上都有严格的限制,在建立表的时候,每一列都必须制定一个数据类型,只有符合该数据类型的数据可以被保存在这一列当中。而在 Sqlite 2.X中,数据类型这个属性只属于数据本生,而不和数据被存在哪一列有关,也就是说数据的类型并不受数据列限制(有一个例外:INTEGER PRIMARY KEY,该列只能存整型数据)。
但是当Sqlite进入到3.0版本的时候,这个问题似乎又有了新的答案,Sqlite的开发者开始限制这种无类型的使用,在3.0版本当中,每一列开始 拥有自己的类型,并且在数据存入该列的时候,数据库会试图把数据的类型向该类型转换,然后以转换之后的类型存储。当然,如果转换被认为是不可行 的,Sqlite仍然会存储这个数据,就像他的前任版本一样。
举个例子,如果你企图向一个INTEGER类型的列中插入一个字符串,Sqlite会检查这个字符串是否有整型数据的特征, 如果有而且可以被数据库所识别,那么该字符串会被转换成整型再保存,如果不行,则还是作为整型存储。

总的来说,所有存在Sqlite 3.0版本当中的数据都拥有以下之一的数据类型:
空(NULL):该值为空
整型(INTEGEER):有符号整数,按大小被存储成1,2,3,4,6或8字节。
实数(REAL):浮点数,以8字节指数形式存储。
文本(TEXT):字符串,以数据库编码方式存储(UTF-8, UTF-16BE 或者 UTF-16-LE)。
BLOB:BLOB数据不做任何转换,以输入形式存储。

ps: 在关系数据库中,CLOB和BLOB类型被用来存放大对象。BOLB表示二进制大对象,这种数据类型通过用来保存图片,图象,视频等。CLOB表示字符大对象,能够存放大量基于字符的数据。

对应的,对于数据列,同样有以下的数据类型:

TEXT 
NUMERIC 
INTEGER 
REAL 
NONE
数据列的属性的作用是确定对插入的数据的转换方向:

TEXT 将数据向文本进行转换,对应的数据类型为NULL,TEXT 或 BLOB 
NUMERIC 将数据向数字进行转换,对应的数据类型可能为所有的五类数据,当试图存入文本 时将执行向整型或浮点类型的转换(视具体的数值而定),转换若不可行,则保留文本类型存储,NULL或BLOB不做变化 
INTEGER 将数据向整型转换,类似于NUMERIC,不同的是没有浮点标志的浮点数将转换为整型保存 
REAL 将数据向浮点数类型转换,类似于NUMERIC,不同的是整数将转换为浮点数保存 
NULL 不做任何转换的数据列类型

实例代码如下,

附件工程可直接编译,例子使用了blob数据类型。

#include "sqlite3.h"                                //包含一个头文件就可以使用所以sqlite的接口了

#include "stdlib.h"

#include "stdio.h"

#include "string.h"

 

#pragma comment(lib, "sqlite.lib")           //我把sqlite编译成了一个静态的lib文件。

 

void       createdb();

void       querydb();

 

int         main()

{

            createdb();

            querydb();

 

            return 0;

}

 

void       createdb()

{

            int                     ret;

            sqlite3               *pdb = 0;

            sqlite3_stmt      *stmt = 0;

            char                  *error = 0;

            char                  *sql = "insert into table1 values('value11',:aaa)";

            int         &nbs;            index;

            static void          *value = "asdfadsfasdfjasdfjaksdfaskjdfakdsfaksfja";

 

            ret = sqlite3_open("db1.sdb", &pdb);                    //打开数据库,跟打开文本文件一样

            if( ret != SQLITE_OK )

                        return;

            ret = sqlite3_exec(pdb, "create table table1(col1 char(20), col2 BLOB)", 0,0, &error );

            if( ret != SQLITE_OK )

                        return;

 

            ret = sqlite3_prepare(pdb, sql,strlen(sql), &stmt, &error);

            if( ret != SQLITE_OK )

                        return;

 

            index = sqlite3_bind_parameter_index(stmt, ":aaa");

 

            ret = sqlite3_bind_blob(stmt, index, value, strlen(value), SQLITE_STATIC);

            if( ret != SQLITE_OK )

                        return;

 

            ret = sqlite3_step(stmt);

           

            if( ret != SQLITE_DONE )

                        return;

 

            sqlite3_close(pdb);        

}

 

void       querydb()

{

            int                     ret;

            sqlite3   *pdb = 0;

            sqlite3_stmt      *pstmt = 0;

            char      *error = 0;

            char      *sql = "select * from table1";

            int                     len;

            int                     i;

            char      *name;

            void       *value;

 

            ret = sqlite3_open("db1.sdb", &pdb);

            if( ret != SQLITE_OK )

                        return;

 

            ret = sqlite3_prepare(pdb, sql, strlen(sql), &pstmt, &error);

            if( ret != SQLITE_OK )

                        return;

 

            while( 1 )

            {

                        ret = sqlite3_step(pstmt);

                        if( ret != SQLITE_ROW )

                                    break;

 

                        name = sqlite3_column_text(pstmt, 0);

                        value = sqlite3_column_blob(pstmt, 1);

                        len = sqlite3_column_bytes(pstmt,1 );

            }

}

 

 

实例二:SQLite中如何用api操作blob类型的字段

 

   在实际的编程开发当中我们经常要处理一些大容量二进制数据的存储,如图片或者音乐等等。对于这些二进制数据(blob字段)我们不能像处理普通的文本那样 简单的插入或者查询,为此SQLite提供了一组函数来处理这种BLOB字段类型。下面的代码演示了如何使用这些API函数。

 

首先我们要建立一个数据库:

sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);

 

//由于mmmm.rar是一个二进制文件,所以要在使用insert语句时先用?号代替

     sqlite3_prepare(db, "insert into list values ('mmmm.rar',?);", -1, &stat, 0);

    

     FILE *fp;

     long filesize = 0;

     char * ffile;

 

     fp = fopen("mmmm.rar", "rb");

 

     if(fp != NULL)

     {

         //计算文件的大小

         fseek(fp, 0, SEEK_END);

         filesize = ftell(fp);

         fseek(fp, 0, SEEK_SET);

 

         //读取文件

         ffile = new char[filesize+1];

         size_t sz = fread(ffile, sizeof(char), filesize+1, fp);

             

         fclose(fp);

     }

 

     //将文件数据绑定到insert语句中,替换“?”部分

     sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);

    

//执行绑定之后的SQL语句

     sqlite3_step(stat);

这时数据库当中已经有了一条包含BLOB字段的数据。接下来我们要读取这条数据:

    

     //选取该条数据

     sqlite3_prepare(db, "select * from list;", -1, &stat, 0);

     sqlite3_step(stat);

//得到纪录中的BLOB字段

const void * test = sqlite3_column_blob(stat, 1);

//得到字段中数据的长度

     int size = sqlite3_column_bytes(stat, 1);

    

     //拷贝该字段

     sprintf(buffer2, "%s", test);

此时可以将buffer2写入到文件当中,至此BLOB数据处理完毕。

 

实例三:sqlite 中用blob存储图片和取出图片

 

#include<iostream>
#include<string>
#include<sqlite3.h>

using namespace std;

int main()
{
        sqlite3 *db;
sqlite3_stmt *stat;
char *zErrMsg = 0;

char buffer2[1024]="0";


sqlite3_open("./MetaInfo.db", &db);
    int result;

     if(result)
      {
         cout<<"Open the database sqlite.db failed"<<endl;
       }
   
     else
          cout<<"Open the database sqlite.db sucessfully"<<endl;

sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);
sqlite3_prepare(db, "insert into list values ('./data/2.bmp',?);", -1, &stat, 0);

FILE *fp;
long filesize = 0;
char * ffile;

fp = fopen("./data/2.bmp", "rb");

if(fp != NULL)
{
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);

ffile = new char[filesize+1];
size_t sz = fread(ffile, sizeof(char), filesize+1, fp);
   
fclose(fp);
}

sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);
sqlite3_step(stat);

sqlite3_prepare(db, "select * from list;", -1, &stat, 0);
sqlite3_step(stat);

const void * test = sqlite3_column_blob(stat, 1);
int size = sqlite3_column_bytes(stat, 1);

sprintf(buffer2, "%s", test);

FILE *fp2;

fp2 = fopen("outfile.png", "wb");

if(fp2 != NULL)
{
size_t ret = fwrite(test, sizeof(char), size, fp2);
fclose(fp2);
}

delete(ffile);
sqlite3_finalize(stat);
sqlite3_close(db);
   return 0;
}

© 著作权归作者所有

共有 人打赏支持
涩女郎
粉丝 35
博文 104
码字总数 160210
作品 0
浦东
高级程序员
私信 提问
linux c++ sqlite3

1,基本信息: 1)#include <sqlite3.h> 2)int rc = sqlite3open(dbname, &db);//不存在会创建文件 3)查询后直接返回结果 而不是回调 int sqlite3gettable (sqlite3 , // 打开的数据库对象指针...

Carlyle_Lee
2015/03/16
0
0
IOS---数据持久化

1、文件管理 ios沙盒机制: ios应用程序只能在为该程序创建的文件系统中读取文件,不可以去其他地方访问,此区域被称为沙盒,所以所有的非代码文件都要保存在此,例如图像、图标、声音、映像...

一人丨星空
2016/08/30
31
0
UI_19 数据持久化(本地存储)

一、数据持久化概述 数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。 1、数据持久化的方式 1.1 writeToFile:简单对象写入文件 1.2 NSUserDefaults:应用程序偏好...

黑伞将军
2015/09/09
54
0
iOS数据存取(2)

SQLite3 SQLite3简介 SQLite3是一款开源的嵌入式关系型数据库,可移植性好、易使用、内存开销小。 SQLite3是无类型的,意味着你可以保存任何类型的数据到任意表的任意字段中。比如下列的创表...

天机
2016/04/29
23
0
SQLite4 的设计

1.0 内容提要 SQLite4 是一个放在库中的紧凑的,自包含的,零维护的的ACID数据库引擎, 像SQLite3一样, 但具有改进的接口和文件格式. 运行时环境封装到了一个对象之中. 使用了一个很不错的键值...

oschina
2014/05/26
9.3K
22

没有更多内容

加载失败,请刷新页面

加载更多

Hashtable 为什么不叫 HashTable?

前几天在写《HashMap 和 Hashtable 的 6 个区别》这篇文章的时候,差点把 Hashtable 写成了 HashTable,后来看源码证实了是:Hashtable,小写的 "t"able,不符合驼峰命名规则。 什么是驼峰命...

Java技术栈
5分钟前
0
0
Position属性四个值:static、fixed、absolute和relative的区别和用法

静下心来慢慢读,读完一定会有所收获的 static(静态定位):默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 relative(相对定位):生成相...

简心
6分钟前
0
0
Confluence 6 为一个空间应用一个主题

主题允许你对 Confluence 的外表和显示进行自定义。你的 Confluence 空间管理员可以到 The Atlassian Marketplace 上下载主题。 一旦一个主题被安装到 Confluence 后,这个主题可以应用到全站...

honeymose
6分钟前
0
0
python利用os.system执行多条系统命令

先看代码(正确代码): def UpdateCNSubAllInd(): os.system("cd spiders && scrapy runspider CN_UpdateSubIndex.py")def UpdateSSESubAllInd(): os.system("cd spiders && sc......

fang_faye
17分钟前
0
0
容器技术系列汇总

docker docker - 在centos7和windows10安装 docker - 镜像加速器 docker - 构建一个简单的docker镜像 docker - 调试Dockerfile docker - 常用命令 docker - Dockerfile常用指令 docker - doc......

细肉云吞
23分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部