在對移動嵌入式數(shù)據(jù)庫中BLOB數(shù)據(jù)類型分析的基礎(chǔ)上,使用C語言的API函數(shù)調(diào)用移動SQLite數(shù)據(jù)庫語句,并按其訪問模式調(diào)用連接函數(shù),實(shí)現(xiàn)了SQLite移動數(shù)據(jù)庫中二進(jìn)制大對象和C結(jié)構(gòu)體類型數(shù)組的BLOB處理方法。隨著圖像和音視頻數(shù)據(jù)的日益增多,BLOB數(shù)據(jù)類型在SQLite中的應(yīng)用將更為廣闊,給出的Demo實(shí)例驗(yàn)證了這一技術(shù)的有效性。
SQLite移動數(shù)據(jù)庫 BLOB類型 嵌入式開發(fā)
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:1006-1010(2014)-06-
1 引言
移動嵌入式數(shù)據(jù)庫一直是一個熱點(diǎn)應(yīng)用開發(fā),作為輕量級嵌入式移動數(shù)據(jù)庫的典型,SQLite有許多令人印象深刻的優(yōu)點(diǎn),包括:具有開放源代碼;自身程序特別??;支持大多數(shù)SQL命令;速度極快;直接創(chuàng)建數(shù)據(jù)庫,不需要服務(wù)器支持;簡潔的C語言API(Application Programming Interface,應(yīng)用程序編程接口)接口。它具有的零配置安裝可在系統(tǒng)崩潰或電源故障時自動恢復(fù),且數(shù)據(jù)被存儲在單一的物理文件中,數(shù)據(jù)庫運(yùn)行在同一個相互間無通信的進(jìn)程,訪問數(shù)據(jù)庫的程序直接從文件讀取和寫入磁盤,數(shù)據(jù)的讀寫速度快,具有高達(dá)2TB的存儲容量,在提供了存儲BLOB(Binary Large Object,二進(jìn)制大對象)方法的同時,API擴(kuò)展等也提供了強(qiáng)有力的技術(shù)支撐;存儲在SQLite數(shù)據(jù)庫BLOB數(shù)據(jù)類型的輸入數(shù)據(jù)無需任何轉(zhuǎn)換,數(shù)據(jù)本身的屬性就是表的列屬性[1]。
2 BLOB技術(shù)原理
BLOB數(shù)據(jù)類型是適合用于存儲可變長度的二進(jìn)制大對象數(shù)據(jù)以及可變長度的音頻和視頻數(shù)據(jù)。在SQLite的BLOB類型中存儲復(fù)雜的數(shù)據(jù)時,長度是不加限制的[2]。使用B-樹索引來管理和組織屬性數(shù)據(jù),通過SQL語句到數(shù)據(jù)庫相關(guān)數(shù)據(jù)中實(shí)現(xiàn)增、刪、改、查的操作。SQLite不支持靜態(tài)數(shù)據(jù)類型,而是使用列關(guān)系。當(dāng)數(shù)據(jù)記錄的字段內(nèi)容插入到數(shù)據(jù)庫中時,SQLite將對該字段內(nèi)容的類型做檢查,若類型不能匹配到相關(guān)聯(lián)的列,則SQLite會將該字段內(nèi)容轉(zhuǎn)換成列的類型。因此,數(shù)據(jù)庫中BLOB數(shù)據(jù)類型的合理應(yīng)用也直接影響存儲效率和查詢速度的提高。
3 BLOB類型在SQLite中的應(yīng)用
3.1 SQLite的API函數(shù)
嵌入式移動數(shù)據(jù)庫SQLite使用C語言API等接口,在此基礎(chǔ)上的擴(kuò)展也可用于其他語言的SQLite的接口[3]。以下是SQLite中常用的對數(shù)據(jù)庫進(jìn)行操作的函數(shù):
(1)創(chuàng)建和打開數(shù)據(jù)庫
int sqlite3_open(const char*,sqlite3**db);
功能是當(dāng)數(shù)據(jù)庫文件存在時,可以打開已存在的數(shù)據(jù)庫;若不存在,則創(chuàng)建一個新的數(shù)據(jù)庫文件并打開,且能通過輸入?yún)?shù)返回連接。
(2)運(yùn)行函數(shù)
int sqlite3_exec(sqlite3*,const char*sql,sqlite_callback,void*,char**em);
*sql是運(yùn)行的SQL語句,該語句可按實(shí)際需要編寫一條或多條;sqlite_callback是一個回調(diào)函數(shù),根據(jù)實(shí)際可編寫回調(diào)函數(shù)從數(shù)據(jù)庫中獲取需要的結(jié)果。
(3)預(yù)編譯SQL語句的函數(shù)
int sqlite3_prepare(sqlite3*db,const char*iSql,int jByte,sqlite3_stmt**pStmt,const char**pl);
該函數(shù)需要一個數(shù)據(jù)庫連接的指針,將給定的SQL文本轉(zhuǎn)換為預(yù)聲明語句對象并返回一個指向它的指針,這個函數(shù)并不執(zhí)行SQL語句,只是預(yù)編譯和解析SQL文本,準(zhǔn)備執(zhí)行。
(4)查詢函數(shù)
int sqlite3_get_table(sqlite3*,const char*sql,char ***ret,int*nrow,int*ncol,char**em);
功能是無需回調(diào)函數(shù)處理,直接能查詢結(jié)果集。
3.2 SQLite數(shù)據(jù)庫BLOB類型應(yīng)用實(shí)例
(1)SQLite二進(jìn)制大對象處理技術(shù)
在實(shí)際編程開發(fā)中,往往是進(jìn)行二進(jìn)制大對象數(shù)據(jù)的訪問,如圖像、音視頻等。對于這些數(shù)據(jù)不能像對待普通的文本一樣插入或查詢那樣簡單,而是將圖像等文件在使用Insert或Update語句時先用通配符‘?代替,通配符‘?表示未定值是一個占位符,然后通過sqlite3_bind_blob綁定到Insert或Update中,替換‘?部分并存儲。如果是字符串,則還需要通過sqlite3_bind_parameter_index()獲取對應(yīng)的index,然后再調(diào)用sqlite3_bind_blob()操作。通常也用于構(gòu)造不定條件的動態(tài)SQL語句。
以下的Demo1.c程序就實(shí)現(xiàn)了SQLite數(shù)據(jù)庫中圖像的存取處理[4]:
//創(chuàng)建表函數(shù)
int CreateTab(sqlite3*db)
{char*EM=0; //*EM指針返回錯誤消息
char*sql="CREATE TABLE xuch(BH primart key,MC varchar(10),SL int,SB blob); "
if(SQLITE_OK)!=sqlite3_exec(db, 0,0,&EM))
{printf(" failed:%s\n",EM);}
}
//插入數(shù)據(jù)記錄并處理大對象數(shù)據(jù)函數(shù)
int InsertRec(sqlite3*db)
{……endprint
char*sql="INSERT INTO xuch(BH,MC,SL) VALUES(‘20121001,Computer,20); "
……
char*sql="UPDATE xuch SET SB=? WHERE MC='Computer';" //‘?通配符是占位符代替二進(jìn)制文件
}
……//此處需應(yīng)有為占位符‘?所提供的圖像視頻等大對象文件的打開等操作
sqlite3_bind_blob(stmt, 1, fl, fs, NULL);//調(diào)用該函數(shù)使Update中‘?代表的參數(shù)傳入對應(yīng)字段,其中的stmt記錄了SQL語句。
如果有多個‘?,就需要寫出多個sqlite3_bind_blob語句,并改變它們的第2個參數(shù)即可替換到不同的‘?。最后使用sqlite3_step將二進(jìn)制數(shù)據(jù)保存到對應(yīng)的數(shù)據(jù)庫中。
(2)C結(jié)構(gòu)體類型在BLOB中的處理技術(shù)
將一個結(jié)構(gòu)體數(shù)據(jù)以二進(jìn)制的方式寫入到SQLite數(shù)據(jù)庫的BLOB類型中,并顯示出結(jié)果。
Demo2.c程序主要代碼如下所示,其中personal是一個結(jié)構(gòu)體數(shù)組。
sqlite3*db;
sqlite3_open("test.db", &db);
sqlite3_stmt*stmt;
typedef struct xuchunhua
{ int no;
char name[10];
bool sex;
}teacher;
teacher personal[20];
……
personal[1].no=10;
strcpy(personal[1].name,“LiuBing”);
personal[i].bool=1;
……
result=sqlite3_exec(db,"create table xuch(bh text,jg blob)", 0,0,&perrmsg); //創(chuàng)建對應(yīng)的表,這里用到了blob類型
result=sqlite3_prepare(db,"insert into xuch values(?,?)",-1,&stmt,0); //插入數(shù)據(jù),這里采用預(yù)編譯的形式,凡是二進(jìn)制的數(shù)據(jù)都要這樣處理[5]
……
void*buffer ; //創(chuàng)建內(nèi)存指針
buffer=new char(sizeof(teacher)); //初始化存儲空間,sizeof(teacher)為結(jié)構(gòu)體大小
……
result=sqlite3_bind_text(stmt,1,“X1001”, -1,NULL); //綁定表的第一個字段,這里為text類型
result=sqlite3_bind_blob(stmt,2,buffer,sizeof(teacher),NULL); //綁定blob類型
result=sqlite3_step(stmt); //執(zhí)行sql語句,這樣就把數(shù)據(jù)存到數(shù)據(jù)庫里了
……
result=sqlite3_prepare(db,"select jg from xuch
where bh=“X1001”,-1,&stmt,0); //查找一行的數(shù)據(jù)
result=sqlite3_step(stmt);
if(result==SQLITE_ROW)
{
int blob_size=sqlite3_column_bytes(stmt,0)/sizeof(teacher); //獲取數(shù)組的長度
personal1=(teacher*)sqlite3_column_blob(stmt,0); //獲取數(shù)組的頭指針
for(int i=0 ;i {printf("%d",personal[i].sno); printf("%s",personal[i].sname; //輸出數(shù)據(jù) ……} } sqlite3_finalize(stmt); sqlite3_close(db); 4 結(jié)束語 SQLite提供了存取二進(jìn)制大對象BLOB的方法,在嵌入式移動數(shù)據(jù)庫開發(fā)中,可對二進(jìn)制大對象和C結(jié)構(gòu)體使用BLOB類型數(shù)據(jù)處理。SQLite移動數(shù)據(jù)庫的設(shè)計目標(biāo)是嵌入式的,而且目前已經(jīng)在很多嵌入式產(chǎn)品中使用,它占用的資源非常低。SQLite嵌入式移動數(shù)據(jù)庫的易用性,可加快應(yīng)用程序的開發(fā),完全支持復(fù)雜的SQL,對于小型設(shè)備的有限空間來說是特別重要的應(yīng)用。此外,SQL還支持原子的、一致的、獨(dú)立的和持久的(ACID)事務(wù)。SQLite允許多個進(jìn)程同時打開一個數(shù)據(jù)庫,同時讀取數(shù)據(jù)庫實(shí)現(xiàn)并發(fā)處理。隨著應(yīng)用的廣泛,在移動數(shù)據(jù)庫中具有越來越多的圖像數(shù)據(jù)、大文本數(shù)據(jù)、音頻和視頻數(shù)據(jù),在SQLite中BLOB數(shù)據(jù)類型的應(yīng)用將更為廣闊。 參考文獻(xiàn): [1] Michael Owens. The Definitive Guide to SQLite[M]. Berkeley: Apress, 2006. [2] 葉宏祥. 移動存儲關(guān)鍵性技術(shù)的研究及進(jìn)展[J]. 移動通信, 2009(11): 32-34. [3] The Architecture of SQLite[EB/OL]. [2013-08-21]. http://www.sqlite.org/arch.html. [4] 劉玉海,劉冰. SQLite嵌入式數(shù)據(jù)庫及圖象處理技術(shù)研究[J]. 軟件, 2012(8): 102-104. [5] C/C++ Interface for SQLite Version3[EB/OL]. [2013-08-21]. http://www.sqlite.org/capi3ref.html.★
char*sql="INSERT INTO xuch(BH,MC,SL) VALUES(‘20121001,Computer,20); "
……
char*sql="UPDATE xuch SET SB=? WHERE MC='Computer';" //‘?通配符是占位符代替二進(jìn)制文件
}
……//此處需應(yīng)有為占位符‘?所提供的圖像視頻等大對象文件的打開等操作
sqlite3_bind_blob(stmt, 1, fl, fs, NULL);//調(diào)用該函數(shù)使Update中‘?代表的參數(shù)傳入對應(yīng)字段,其中的stmt記錄了SQL語句。
如果有多個‘?,就需要寫出多個sqlite3_bind_blob語句,并改變它們的第2個參數(shù)即可替換到不同的‘?。最后使用sqlite3_step將二進(jìn)制數(shù)據(jù)保存到對應(yīng)的數(shù)據(jù)庫中。
(2)C結(jié)構(gòu)體類型在BLOB中的處理技術(shù)
將一個結(jié)構(gòu)體數(shù)據(jù)以二進(jìn)制的方式寫入到SQLite數(shù)據(jù)庫的BLOB類型中,并顯示出結(jié)果。
Demo2.c程序主要代碼如下所示,其中personal是一個結(jié)構(gòu)體數(shù)組。
sqlite3*db;
sqlite3_open("test.db", &db);
sqlite3_stmt*stmt;
typedef struct xuchunhua
{ int no;
char name[10];
bool sex;
}teacher;
teacher personal[20];
……
personal[1].no=10;
strcpy(personal[1].name,“LiuBing”);
personal[i].bool=1;
……
result=sqlite3_exec(db,"create table xuch(bh text,jg blob)", 0,0,&perrmsg); //創(chuàng)建對應(yīng)的表,這里用到了blob類型
result=sqlite3_prepare(db,"insert into xuch values(?,?)",-1,&stmt,0); //插入數(shù)據(jù),這里采用預(yù)編譯的形式,凡是二進(jìn)制的數(shù)據(jù)都要這樣處理[5]
……
void*buffer ; //創(chuàng)建內(nèi)存指針
buffer=new char(sizeof(teacher)); //初始化存儲空間,sizeof(teacher)為結(jié)構(gòu)體大小
……
result=sqlite3_bind_text(stmt,1,“X1001”, -1,NULL); //綁定表的第一個字段,這里為text類型
result=sqlite3_bind_blob(stmt,2,buffer,sizeof(teacher),NULL); //綁定blob類型
result=sqlite3_step(stmt); //執(zhí)行sql語句,這樣就把數(shù)據(jù)存到數(shù)據(jù)庫里了
……
result=sqlite3_prepare(db,"select jg from xuch
where bh=“X1001”,-1,&stmt,0); //查找一行的數(shù)據(jù)
result=sqlite3_step(stmt);
if(result==SQLITE_ROW)
{
int blob_size=sqlite3_column_bytes(stmt,0)/sizeof(teacher); //獲取數(shù)組的長度
personal1=(teacher*)sqlite3_column_blob(stmt,0); //獲取數(shù)組的頭指針
for(int i=0 ;i {printf("%d",personal[i].sno); printf("%s",personal[i].sname; //輸出數(shù)據(jù) ……} } sqlite3_finalize(stmt); sqlite3_close(db); 4 結(jié)束語 SQLite提供了存取二進(jìn)制大對象BLOB的方法,在嵌入式移動數(shù)據(jù)庫開發(fā)中,可對二進(jìn)制大對象和C結(jié)構(gòu)體使用BLOB類型數(shù)據(jù)處理。SQLite移動數(shù)據(jù)庫的設(shè)計目標(biāo)是嵌入式的,而且目前已經(jīng)在很多嵌入式產(chǎn)品中使用,它占用的資源非常低。SQLite嵌入式移動數(shù)據(jù)庫的易用性,可加快應(yīng)用程序的開發(fā),完全支持復(fù)雜的SQL,對于小型設(shè)備的有限空間來說是特別重要的應(yīng)用。此外,SQL還支持原子的、一致的、獨(dú)立的和持久的(ACID)事務(wù)。SQLite允許多個進(jìn)程同時打開一個數(shù)據(jù)庫,同時讀取數(shù)據(jù)庫實(shí)現(xiàn)并發(fā)處理。隨著應(yīng)用的廣泛,在移動數(shù)據(jù)庫中具有越來越多的圖像數(shù)據(jù)、大文本數(shù)據(jù)、音頻和視頻數(shù)據(jù),在SQLite中BLOB數(shù)據(jù)類型的應(yīng)用將更為廣闊。 參考文獻(xiàn): [1] Michael Owens. The Definitive Guide to SQLite[M]. Berkeley: Apress, 2006. [2] 葉宏祥. 移動存儲關(guān)鍵性技術(shù)的研究及進(jìn)展[J]. 移動通信, 2009(11): 32-34. [3] The Architecture of SQLite[EB/OL]. [2013-08-21]. http://www.sqlite.org/arch.html. [4] 劉玉海,劉冰. SQLite嵌入式數(shù)據(jù)庫及圖象處理技術(shù)研究[J]. 軟件, 2012(8): 102-104. [5] C/C++ Interface for SQLite Version3[EB/OL]. [2013-08-21]. http://www.sqlite.org/capi3ref.html.★
char*sql="INSERT INTO xuch(BH,MC,SL) VALUES(‘20121001,Computer,20); "
……
char*sql="UPDATE xuch SET SB=? WHERE MC='Computer';" //‘?通配符是占位符代替二進(jìn)制文件
}
……//此處需應(yīng)有為占位符‘?所提供的圖像視頻等大對象文件的打開等操作
sqlite3_bind_blob(stmt, 1, fl, fs, NULL);//調(diào)用該函數(shù)使Update中‘?代表的參數(shù)傳入對應(yīng)字段,其中的stmt記錄了SQL語句。
如果有多個‘?,就需要寫出多個sqlite3_bind_blob語句,并改變它們的第2個參數(shù)即可替換到不同的‘?。最后使用sqlite3_step將二進(jìn)制數(shù)據(jù)保存到對應(yīng)的數(shù)據(jù)庫中。
(2)C結(jié)構(gòu)體類型在BLOB中的處理技術(shù)
將一個結(jié)構(gòu)體數(shù)據(jù)以二進(jìn)制的方式寫入到SQLite數(shù)據(jù)庫的BLOB類型中,并顯示出結(jié)果。
Demo2.c程序主要代碼如下所示,其中personal是一個結(jié)構(gòu)體數(shù)組。
sqlite3*db;
sqlite3_open("test.db", &db);
sqlite3_stmt*stmt;
typedef struct xuchunhua
{ int no;
char name[10];
bool sex;
}teacher;
teacher personal[20];
……
personal[1].no=10;
strcpy(personal[1].name,“LiuBing”);
personal[i].bool=1;
……
result=sqlite3_exec(db,"create table xuch(bh text,jg blob)", 0,0,&perrmsg); //創(chuàng)建對應(yīng)的表,這里用到了blob類型
result=sqlite3_prepare(db,"insert into xuch values(?,?)",-1,&stmt,0); //插入數(shù)據(jù),這里采用預(yù)編譯的形式,凡是二進(jìn)制的數(shù)據(jù)都要這樣處理[5]
……
void*buffer ; //創(chuàng)建內(nèi)存指針
buffer=new char(sizeof(teacher)); //初始化存儲空間,sizeof(teacher)為結(jié)構(gòu)體大小
……
result=sqlite3_bind_text(stmt,1,“X1001”, -1,NULL); //綁定表的第一個字段,這里為text類型
result=sqlite3_bind_blob(stmt,2,buffer,sizeof(teacher),NULL); //綁定blob類型
result=sqlite3_step(stmt); //執(zhí)行sql語句,這樣就把數(shù)據(jù)存到數(shù)據(jù)庫里了
……
result=sqlite3_prepare(db,"select jg from xuch
where bh=“X1001”,-1,&stmt,0); //查找一行的數(shù)據(jù)
result=sqlite3_step(stmt);
if(result==SQLITE_ROW)
{
int blob_size=sqlite3_column_bytes(stmt,0)/sizeof(teacher); //獲取數(shù)組的長度
personal1=(teacher*)sqlite3_column_blob(stmt,0); //獲取數(shù)組的頭指針
for(int i=0 ;i {printf("%d",personal[i].sno); printf("%s",personal[i].sname; //輸出數(shù)據(jù) ……} } sqlite3_finalize(stmt); sqlite3_close(db); 4 結(jié)束語 SQLite提供了存取二進(jìn)制大對象BLOB的方法,在嵌入式移動數(shù)據(jù)庫開發(fā)中,可對二進(jìn)制大對象和C結(jié)構(gòu)體使用BLOB類型數(shù)據(jù)處理。SQLite移動數(shù)據(jù)庫的設(shè)計目標(biāo)是嵌入式的,而且目前已經(jīng)在很多嵌入式產(chǎn)品中使用,它占用的資源非常低。SQLite嵌入式移動數(shù)據(jù)庫的易用性,可加快應(yīng)用程序的開發(fā),完全支持復(fù)雜的SQL,對于小型設(shè)備的有限空間來說是特別重要的應(yīng)用。此外,SQL還支持原子的、一致的、獨(dú)立的和持久的(ACID)事務(wù)。SQLite允許多個進(jìn)程同時打開一個數(shù)據(jù)庫,同時讀取數(shù)據(jù)庫實(shí)現(xiàn)并發(fā)處理。隨著應(yīng)用的廣泛,在移動數(shù)據(jù)庫中具有越來越多的圖像數(shù)據(jù)、大文本數(shù)據(jù)、音頻和視頻數(shù)據(jù),在SQLite中BLOB數(shù)據(jù)類型的應(yīng)用將更為廣闊。 參考文獻(xiàn): [1] Michael Owens. The Definitive Guide to SQLite[M]. Berkeley: Apress, 2006. [2] 葉宏祥. 移動存儲關(guān)鍵性技術(shù)的研究及進(jìn)展[J]. 移動通信, 2009(11): 32-34. [3] The Architecture of SQLite[EB/OL]. [2013-08-21]. http://www.sqlite.org/arch.html. [4] 劉玉海,劉冰. SQLite嵌入式數(shù)據(jù)庫及圖象處理技術(shù)研究[J]. 軟件, 2012(8): 102-104. [5] C/C++ Interface for SQLite Version3[EB/OL]. [2013-08-21]. http://www.sqlite.org/capi3ref.html.★