日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux平台上SQLite数据库教程(二)——C语言API介绍

發布時間:2023/11/30 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux平台上SQLite数据库教程(二)——C语言API介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/u011192270/article/details/48086961

前言:本文將介紹幾個基本的SQLite3數據庫的C語言API接口,主要用到兩個文件:sqlite3.c、sqlite3.h。源碼地址:https://github.com/AnSwErYWJ/SQLite。

打開數據庫

1.原型:

int sqlite3_open(const char* filename, /* 數據庫文件名, 必須為 UTF-8 格式 */sqlite3** ppDB /* 輸出: SQLite 數據庫句柄 */ );;
  • 1
  • 2
  • 3
  • 4

2.說明:?
參數filename為指定打開的數據庫, sqlite3的結構指針?*ppDB?為數據庫連接句柄。如果數據庫被成功打開(和/或 創建), 函數返回?SQLITE_OK;否則返回一個錯誤碼, 可以通過* sqlite3_errmsg()* 查看錯誤原因.。出錯,則只可能是?SQLite?無法為?SQLite?對象分配內存空間, 此時將返回 NULL。

關閉數據庫

1.原型:

int sqlite3_close(sqlite3* pDB /* 由 sqlite3_open 或基相關的函數打開的 SQLite 對象句柄 */);
  • 1
  • 2
  • 3

2.說明:?
該函數用來關閉 sqlite3 對象。返回?SQLITE_OK?表示對象被成功關閉,以及所有相關的資源被成功回收。應用程序必須在關閉之前 “完成(finalize)” 所有的 “預編譯語句(prepared statements)”, 并且關閉所有的 “二進制句柄綁定(BLOB handle)”, 如果在關閉時還有未完成的預編譯語句或二進制句柄, 那么函數返回 SQLITE_BUSY(5)。

錯誤處理

原型1:

const char *sqlite3_errmsg(sqlite3* pDB /* SQLite3 數據庫句柄 */ );
  • 1
  • 2
  • 3

說明1:?
該函數返回與pDB數據庫指針相關的錯誤信息,下次調用會覆蓋。

原型2:

int sqlite3_errcode(sqlite3* pDB /* SQLite3 數據庫句柄 */ )
  • 1
  • 2
  • 3

說明2:?
該函數返回最近一次調用 sqlite3_ API時產生的錯誤碼。

示例一:

/************************************************************************* > File Name: example1.c > Author: AnSwEr > Mail: 1045837697@qq.com > Created Time: 2015年08月29日 星期六 14時17分21秒************************************************************************/#include<stdio.h> #include<stdlib.h> #include"sqlite3.h"int main(void) { char *filename = "./first.db"; sqlite3 *pDB = NULL; int ret = 0; ret = sqlite3_open(filename,&pDB); if(ret != SQLITE_OK) { fprintf(stderr,"%s\n",sqlite3_errmsg(pDB)); exit(EXIT_FAILURE); } /*do something*/ printf("open successfully!\n"); if(pDB != NULL) { sqlite3_close(pDB); pDB = NULL; } printf("close successfully!\n"); return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

示例一實現打開和關閉操作。

執行sql語句

原型:

int sqlite3_exec(sqlite3* pDB, /* sqlite3句柄 */const char* sql, /* 被執行的 SQL 語句 */int (*callback)(void*,int,char**,char**), /* 執行/查詢回調函數 */void* pvoid, /* 傳遞給回調函數的第一個參數 */char**errmsg /* 錯誤輸出信息 */ );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

說明:?
當回調函數不為?NULL, 則它對每一個行查詢結果都會調用該回調函數;如果沒有回調函數被指定,?sqlite3_exec()?只是簡單地忽略查詢結果。?
如果回調函數返回非零,sqlite3_exec()?立即中斷查詢,并且不再執行后續的?SQL?語句,也不再調用回調函數,?sqlite3_exec()?將返回?SQLITE_ABORT?結束執行。?
當發生錯誤時, 執行將中斷。如果?errmsg?參數不為空,錯誤信息將會被寫入(errmsg?由?sqlite3_malloc()?分配內存空間,由sqlite3_free()?釋放該內存空間)。如果?errmsg?參數不為?NULL, 并且沒有錯誤發生, errmsg 被設置為?NULL。?
通常情況下callbackselect操作中會使用到,如果不需要回調函數。第三第四個參數設為NULL

回調函數原型:

int callback(void *params, /*params是sqlite3_exec傳入的第四個參數*/int column_size, /*column_size是結果字段的個數*/char **column_value, /*column_value是返回記錄的一位字符數組指針*/char **column_name /*column_name是結果字段的名稱*/ );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

示例二

/*************************************************************************> File Name: example2.c> Author: AnSwEr> Mail: 1045837697@qq.com> Created Time: 2015年08月29日 星期六 20時11分06秒************************************************************************//** 查詢數據庫*/ #include<stdio.h> #include<stdlib.h> #include"sqlite3.h"static print_info(void *params,int column_size,char **column_value,char **column_name) {int i;for(i=0;i<column_size;i++)printf("\t%s",column_value[i]);printf("\n");return 0; }int main(void) {char *filename = "./first.db";sqlite3 *pDB = NULL;int ret = 0;/*open*/ret = sqlite3_open(filename,&pDB);if(ret != SQLITE_OK){fprintf(stderr,"%s\n",sqlite3_errmsg(pDB));exit(EXIT_FAILURE);}/*select*/char *errmsg = 0;ret = sqlite3_exec(pDB,"select * from stutable",print_info,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"select error:%s\n",errmsg);sqlite3_free(errmsg);/*close*/if(pDB != NULL){sqlite3_close(pDB);pDB = NULL;}return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

示例二執行使用回調函數的select語句。此外,還有不使用回調函數的select語句(使用sqlite3_get_table,此函數是sqlite3_exec的包裝)。 不過個人感覺還是使用回調函數好,這樣代碼可看性強,更整潔。

sqlite3_get_table原型:

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 */ ); void sqlite3_free_table(char **result);/* db是sqlite3的句柄 zSql是要執行的sql語句 pazResult是執行查詢操作的返回結果集 pnRow是記錄的行數 pnColumn是記錄的字段個數 pzErrmsg是錯誤信息pazResult是一個(pnRow+1)*pnColumn結果集的字符串數組,其中前pnColumn個結果是字段的名稱,后pnRow行記錄是真實的字段值,如果某個字段為空,則對應值為NULL。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這里貼一段網上查到的不使用回調函數的select示例:

char **dbresult; int j,nrow,ncolumn,index; //select tableret = sqlite3_get_table(db,"select * from t",&dbresult,&nrow,&ncolumn,&errmsg);if(ret == SQLITE_OK){printf("query %i records.\n",nrow);index=ncolumn;for(i=0;i<nrow;i++){printf("[%2i]",i);for(j=0;j<ncolumn;j++){printf(" %s",dbresult[index]);index++;}printf("\n");}}sqlite3_free_table(dbresult);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

示例三

/*************************************************************************> File Name: example3.c> Author: AnSwEr> Mail: 1045837697@qq.com> Created Time: 2015年08月29日 星期六 20時44分10秒************************************************************************//** 表的創建與刪除,數據的插入,更新與刪除。*/#include<stdio.h> #include<stdlib.h> #include"sqlite3.h"static print_info(void *params,int column_size,char **column_value,char **column_name) {int i;for(i=0;i<column_size;i++)printf("\t%s",column_value[i]);printf("\n");return 0; }int main(void) {char *filename = "./first.db";sqlite3 *pDB = NULL;int ret = 0;/*open*/ret = sqlite3_open(filename,&pDB);if(ret != SQLITE_OK){fprintf(stderr,"%s\n",sqlite3_errmsg(pDB));exit(EXIT_FAILURE);}/*創建表*/const char *create_table = "create table t(id int primary key,name vachar(128))";char *errmsg = 0;ret = sqlite3_exec(pDB,create_table,NULL,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"create table error:%s\n",errmsg);sqlite3_free(errmsg);/*插入數據*/const char *insert_data = "insert into t(id,name) values(1,'answer')";ret = sqlite3_exec(pDB,insert_data,NULL,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"insert data error:%s\n",errmsg);/*查詢表中數據*/ret = sqlite3_exec(pDB,"select * from t",print_info,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"select error:%s\n",errmsg);printf("\n");/*更新表中數據*/const char *update_data = "update t set name='jack' where id=1";ret = sqlite3_exec(pDB,update_data,NULL,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"update_data error:%s\n",errmsg);/*查詢表中數據*/ret = sqlite3_exec(pDB,"select * from t",print_info,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"select error:%s\n",errmsg);printf("\n");/*刪除數據*/const char *delete_data = "delete from t where id = 1";ret = sqlite3_exec(pDB,delete_data,NULL,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"delete data error:%s\n",errmsg);/*查詢受上次操作影響的記錄數*/printf("delete data records:%i\n",sqlite3_changes(pDB));printf("\n");/*刪除表*/const char *drop_table = "drop table if exists t";ret = sqlite3_exec(pDB,drop_table,NULL,NULL,&errmsg);if(ret != SQLITE_OK)fprintf(stderr,"drop table error:%s\n",errmsg);/*close*/if(pDB != NULL){sqlite3_close(pDB);pDB = NULL;}return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

示例三演示創建\刪除表,數據的插入、更新與刪除。

預編譯操作

注意:sqlite3_exec中已經封裝了預編譯操作,直接使用即可,預編譯操作只需稍作了解。

網上查了很多sqlite的預編譯操作的例子,比較復雜,大致可以分為以下幾個步驟:?
1. 通過sqlite3_prepare創建一個sqlite3_stmt對象?
2. 通過sqlite3_bind_*()綁定預編譯字段的值?
3. 通過sqlite3_step()執行SQL語句?
4. 通過sqlite3_reset()重置預編譯語句,重復操作2多次?
5. 通過sqlite3_finalize()銷毀資源

下面依次來看看這些函數。

sqlite3_prepare原型:

int sqlite3_prepare(sqlite3* pDB, /* 成功打開的數據庫句柄 */const char* sql, /* UTF8編碼的 SQL 語句 */int nbytes, /* 參數 sql 的字節數, 包含 '\0' */sqlite3_stmt** ppStmt, /* 輸出:預編譯語句句柄 */const char** pszTail /* 輸出:指向 sql 語句中未使用的部分 */ );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

說明:?
如果nbytes小于0,?sql?語句則以第一個 ‘\0’終結。如果它非負,,則為讀取的最大長度.。當nbytes?大于 0 時,則讀取指定長度,如果’\0’先被讀到,則以’\0’結束。如果用戶知道被傳入的 sql 語句是以 ‘\0’ 結尾的,那么有一個更好的做法是:把nbytes的值設為該字符串的長度(包含’\0’),這樣可以避免 SQLite 復制該字符串的一份拷貝, 以提高程序的效率。?
如果?pszTail?不為 NULL, 則?*pszTail?指向?sql?中第一個被傳入的 SQL 語句的結尾。該函數只編譯?sql?的第一個語句, 所以 *pszTail 指向的內容則是未被編譯的。?
*ppStmt?指向一條可以被?sqlie3_step()?函數使用的預編譯語句.。如果有錯誤發生,?pszStmt 的值為*NULL。?
調用者應該使用?sqlite3_finalize()?刪掉被預編譯的語句。?
如果函數成功, 返回?SQLITE_OK, 否則返回一個錯誤碼。

sqlite3_bind_*有多種形式,分別對應不同的數據類型:

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); int sqlite3_bind_double(sqlite3_stmt*, int, double); int sqlite3_bind_int(sqlite3_stmt*, int, int); int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); int sqlite3_bind_null(sqlite3_stmt*, int); int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

預編譯SQL語句中可以包含如下幾種形式:

? ?NNN :VVV @VVV $VVV
  • 1
  • 2
  • 3
  • 4
  • 5

NNN代表數字,VVV代表字符串.?
如果是?或者?NNN,那么可以直接sqlite3_bind_*()進行操作,如果是字符串,還需要通過sqlite3_bind_parameter_index()獲取對應的index,然后再調用sqlite3_bind_*()操作。這通常用于構造不定條件的SQL語句(動態SQL語句)。

int sqlite3_step原型:

int sqlite3_step(sqlite3_stmt* ppStmt /* 一條被預編譯的 sql 語句 */ );
  • 1
  • 2
  • 3

說明:?
當一條語句被 sqlite3_prepare() 或其相關的函數預編譯后, sqlite3_step() 必須被調用一次或多次來評估該預編譯語句。?
該函數的詳細行為依賴于由 sqlite3_prepare()(或其相關的函數) 產生的是一條怎樣的預編譯語句。

返回值:?
SQLITE_BUSY:忙碌. 數據庫引擎無法鎖定數據去完成其工作。但可以多次嘗試。?
SQLITE_DONE:完成. sql 語句已經被成功地執行。在調用 sqlite_reset() 之前, 當前預編譯的語句不應該被 sqlite3_step() 再次調用。?
SQLITE_ROW:查詢時產生了結果。此時可以通過相關的”數據訪問函數(column access functions)”來取得數據. sqlite3_step() 的再一次調用將取得下一條查詢結果。?
SQLITE_ERROR:發生了錯誤。 此時可以通過 sqlite3_errmmsg() 取得相關的錯誤信息. sqlite3_step() 不能被再次調用。?
SQLITE_MISUSE:不正確的庫的使用. 該函數使用不當。

sqlite3_finalize原型:

int sqlite3_finalize(sqlite3_stmt* pStmt /* 被預編譯的語句 */ );
  • 1
  • 2
  • 3

說明:?
該函數用來刪除一條被預編譯的 sql 語句。

預編譯實現代碼:

int i = 0;sqlite3_stmt *stmt;char ca[255];//預編譯操作sqlite3_prepare_v2(db,"insert into t(id,msg) values(?,?)",-1,&stmt,0);for(i=10;i<20;i++){sprintf(ca,"HELLO#%i",i);sqlite3_bind_int(stmt,1,i);sqlite3_bind_text(stmt,2,ca,strlen(ca),NULL);sqlite3_step(stmt);sqlite3_reset(stmt);}sqlite3_finalize(stmt);stmt = NULL;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

總結

上文列出的是一些最基本精簡的C語言API,sqlite為C語言一共提供了200多個API。不過,上述這些API對一般的開發者而言已經足夠了,如果你還有更多的需求,那就請查閱前言中給出的源代碼文件(sqlite3.c,sqlite3.h)。

反饋與建議

  • 微博:@AnSwEr不是答案
  • github:AnSwErYWJ
  • 博客:AnSwEr不是答案的專欄

總結

以上是生活随笔為你收集整理的Linux平台上SQLite数据库教程(二)——C语言API介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。