SQLite 裏最常用的就是 sqlite3* 類型,從數據庫打開開始,sqlite就要爲這個類型準備好內存,直到數據庫關閉,整個過程都要用到這個類型,從數據庫打開開始,這個類型的變量就代表了你要操作的數據庫。
sqlite3 *database;
不要忘記在工程中加入庫文件libsqlite3.dylib和頭文件#import<sqlite3.h>
1.打開數據庫
int sqlite3_open(const char *filename, sqlite3 **ppDb);
第1個參數是數據庫文件地址,比如,"~/Hunk/MyFiles/database.sqlite3",iOS中常用的是放在Sandbox下的路徑,比如放在Documents文件夾下,此文件名不需要一定存在,如果不存在,SQLite會自動創建它;如果存在,就直接打開數據庫文件.因爲此處是const char * 的參數在iOS中需要通過UTF8String做一個簡單的轉換- (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:@"database.sqlite3"];
}
第2個參數是sqlite**,傳入sqlite3*的指針即可。
函數返回值表示操作是否正確,如果是SQLITE_OK表示操作正常。
int result = sqlite3_open([[self dataFilePath] UTF8String], database);
2.關閉數據庫
int sqlite3_colse(sqlite3 **ppDb);
如果數據庫打開成功,那麼一定要關閉數據庫。
3.SQL語句執行操作
int sqlite3_exec(sqlite*, const char * sql, int(*callback), void*, char* errmsg);
第1個參數就是sqlite3*;
第2個參數就是sql語句,如:const char *sql = "select * from my_table";
第3個參數是一個回調函數,當這條語句執行完之後就會去調用你提供的這個函數;
第4個參數是你所提供的指針,可以傳遞任何一個指針參數到這裏,這個參數最終會傳到回調函數裏面,如果不需要傳遞函數指針給回調函數,填NULL即可。
第5個參數是錯誤信息,是指針的指針。執行失敗時可以輸出這個指針所指的信息。
printf(“%s\n”,errmsg)
通常, 回調函數 和它後面的 void * 這兩個位置都可以填 NULL。填 NULL 表示你不需要回調。比如你做 insert 操作,做 delete 操作,就沒有必要使用回調。而當你做 select 時,就要使用回調,因爲 sqlite3 把數據查出來,得通過回調告訴你查出了什麼數據,特殊情況特殊對待。
sqlite3_exec(database, "select * from my_table", callbackInfo, NULL, &errorMsg);
sqlite3_exec函數的回調函數
int (*callback)(void*,int,char**,char**)
回調函數必須定義成上面函數的形式。
第1個參數你可以傳入一些特殊的指針(比如類指針、結構指針),然後在這裏面強制轉換成對應的類型(這裏面是void*類型,必須強制轉換成你的類型纔可用)。然後操作這些數據。
第2個參數n_column是這一條記錄有多少個字段(這條記錄有多少列)
第3個參數char ** column_value是個關鍵值,查出來的數據都保存在這裏,它實際上是個1維數組(不要以爲是2維數組),每一個元素都是一個char *值,是一個字段內容(用字符串來表示,以\0 結尾)
第4個參數char ** column_name 跟column_value是對應的,表示這個字段的字段名稱。
int callbackInfo(void *para, int n_column, char **column_value, char **column_name)
{
// 取值成功
for (int i = 0; i < strlen(*column_value); i++)
{
for(int j = 0; j < n_column; j++)
{
// NSLog(@"字段名:%@---字段值:%@\n", result[j], result[index]);
printf( "字段名:%s > 字段值:%s\n", column_name[j], column_value[j]);
}
}
return 0;
}
4.數據庫操作
關鍵在於sql語句。
創建表: create table my_table(id integer primary key autoincrement, name varchar(32), description text)
插入數據:insert into my_table(name, description) values('Hunk', '男');
5.不使用回調函數查詢數據庫
int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
第1,2個參數不必多說;
if(sqlite3_get_table(database, "select * from my_table", &result, &nRow, &nColumn, &errorMsg) == SQLITE_OK)
{
// 取值成功
for(int i = 0; i < nRow; i++)
{
for(int j = 0; j < nColumn; j++)
{
printf( "字段名:%s > 字段值:%s\n", result[j], result [index]);
++index;
}
}
sqlite3_free_table(result);
}
sqlite3_free_table(result);
6.寫入二進制數據
sqlite操作二進制數據需要用一個輔助的數據類型:sqlite3_stmt *。這個數據類型記錄了一個“sql 語句”。爲什麼我把 “sql 語句” 用雙引號引起來?因爲你可以把sqlite3_stmt *所表示的內容看成是sql語句,但是實際上它不是我們所熟知的sql語句。它是一個已經把sql語句解析了的、用sqlite自己標記記錄的內部數據結構 。正因爲這個結構已經被解析了 ,所以你可以往這個語句裏插入二進制數據。當然,把二進制數據插到 sqlite3_stmt 結構裏可不能直接std::string 那樣用+ 號。必須用 sqlite 提供的函數來插入。
const char *sql = "create table my_table(id integer primary key autoincrement, content blob)";
聲明statement
sqlite3_stmt *statement;
通過sqlite_prepare把sql語句解析到statement裏
sqlite3_prepare(database, "insert into my_table(id, content, description) values(13, ?, ?)", -1, statement, 0);
第3個參數寫的是-1,這個參數意思是前面sql語句的長度。如果小於0,sqlite會自動計算它的長度(把 sql 語句當成以\0 結尾的字符串);
如果這個函數執行成功(返回值是SQLITE_OK 且statement 不爲 NULL ),那麼下面就可以開始插入二進制數據
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
sqlite3_bind_blob(statement, 1, &pdata, 100, NULL)
sqlite3_bind_blob(statement, 2, &pdata, 200, NULL)
第2個參數 ?(前面prepare語句裏有一個?(問號))的索引,假如有多個?號怎麼插入?方法就是改變 bind_blob 函數第 2 個參數。這個參數我寫 1,表示這裏插入的值要替換 statement 的第一個 ?號(這裏的索引從 1 開始計數,而非從 0 開始)。如果你有多個 ?號,就寫多個 bind_blob 語句,並改變它們的第 2 個參數就替換到不同的?號。如果有?號沒有替換,sqlite 爲它取值 null;
第3個參數是二進制數據的其實指針;
第4個參數是二進制數據的長度,以字節爲單位;
第5個參數是個析夠回調函數,告訴sqlite當把數據處理完後調用此函數來析夠你的數據。
bind 完了之後,二進制數據就進入了你的“sql 語句”裏了。你現在可以把它保存到數據庫裏 :
int result = sqlite3_step(statement);
通過這個語句,statement 表示的sql語句就被寫到了數據庫裏。
最後,要把sqlite3_stmt結構給釋放:(把剛纔分配的內容析構掉)
sqlite3_finalize(statement);
7.讀出二進制數據
sqlite3_stmt *statement;
if(SQLITE_OK == sqlite3_prepare(database, "select * from my_table", -1, &statement, NULL))
{
while(SQLITE_ROW == sqlite3_step(statement)) // SQLITE_ROW 100)
{
int nID = sqlite3_column_int(statement, 0);
const void *content = sqlite3_column_blob(statement, 1);
int length = sqlite3_column_bytes(statement, 1);
NSLog(@"%d---%d", nID, length);
}
sqlite3_finalize(statement);
}
int result = sqlite3_step(statement);這一句的返回值是SQLITE_ROW時表示成功(不是SQLITE_OK).
循環執行 sqlite3_step 函數,一次step查詢出一條記錄。直到返回值不爲SQLITE_ROW,時表示查詢結束。
int sqlite3_column_int(sqlite3_stmt*,int iCol);
第2個參數表示獲取第幾個字段的內容,因爲我的id是第一個字段,從0開始計算,所以填0
獲取content的值,content的值是二進制數據,那麼需要獲取到它的指針和長度
const void *content = sqlite3_column_blob(statement, 1);
int length = sqlite3_column_bytes(statement, 1);
析構statementsqlite3_finalize(statement);
8.重複使用 sqlite3_stmt結構
result = sqlite3_reset(statement);