1:經常使用接口 ios
我的比較喜歡sqlite, 使用最方便,惟一的準備工做是下載250K的源;並且做者很熱心,有問必答。 sql
如下演示一下使用sqlite的步驟,先建立一個數據庫,而後查詢其中的內容。2個重要結構體和5個主要函數: 數據庫
sqlite3 *pdb, 數據庫句柄,跟文件句柄FILE很相似 編程
sqlite3_stmt *stmt, 這個至關於ODBC的Command對象,用於保存編譯好的SQL語句 api
sqlite3_open(), 打開數據庫 函數
sqlite3_exec(), 執行非查詢的sql語句 編碼
sqlite3_prepare(), 準備sql語句,執行select語句或者要使用parameter bind時,用這個函數(封裝了sqlite3_exec). spa
Sqlite3_step(), 在調用sqlite3_prepare後,使用這個函數在記錄集中移動。 視頻
Sqlite3_close(), 關閉數據庫文件 sqlite
還有一系列的函數,用於從記錄集字段中獲取數據,如
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; }