嵌入式數(shù)據(jù)共3篇,本片是最后一篇。
《嵌入式數(shù)據(jù)庫(kù)sqlite3【基礎(chǔ)篇】-基本命令操作,小白一看就懂》
《嵌入式數(shù)據(jù)庫(kù)sqlite3【進(jìn)階篇】-子句和函數(shù)的使用,小白一文入門(mén)》
sqlite3編程接口非常多,對(duì)于初學(xué)者來(lái)說(shuō),我們暫時(shí)只需要掌握常用的幾個(gè)函數(shù),其他函數(shù)自然就知道如何使用了。
數(shù)據(jù)庫(kù)
本篇假設(shè)數(shù)據(jù)庫(kù)為my.db,有數(shù)據(jù)表student。
nonamescore4一口Linux89.0
創(chuàng)建表格語(yǔ)句如下:
CREATE TABLE IF NOT EXISTS student (no integer primary key, name text, score real);
常用函數(shù)
sqlite3_open
int sqlite3_open(char *path, sqlite3 **db);功能: 打開(kāi)sqlite數(shù)據(jù)庫(kù)參數(shù): path: 數(shù)據(jù)庫(kù)文件路徑 db: 指向sqlite句柄的指針,后面對(duì)數(shù)據(jù)庫(kù)所有的操作都要依賴(lài)這個(gè)句柄返回值: 成功返回0,失敗返回錯(cuò)誤碼(非零值)
sqlite3_close
int sqlite3_close(sqlite3 *db);功能: 關(guān)閉sqlite數(shù)據(jù)庫(kù)返回值: 成功返回0,失敗返回錯(cuò)誤碼
const char *sqlite3_errmsg(sqlite3 *db);功能: 打印錯(cuò)誤信息 返回值: 返回錯(cuò)誤信息
不使用回調(diào)函數(shù)執(zhí)行SQL語(yǔ)句
sqlite3_get_table
int sqlite3_get_table(sqlite3 *db, const char *sql, char ***resultp, int*nrow, int *ncolumn, char **errmsg);
功能: 執(zhí)行SQL操作參數(shù):
db:數(shù)據(jù)庫(kù)句柄 sql:SQL語(yǔ)句
resultp:用來(lái)指向sql執(zhí)行結(jié)果的指針
nrow:滿足條件的記錄的數(shù)目
ncolumn:每條記錄包含的字段數(shù)目
errmsg:錯(cuò)誤信息指針的地址
返回值: 成功返回0,失敗返回錯(cuò)誤碼
舉例
下面比如我們要顯示student表中所有的數(shù)據(jù)信息,我們就可以利用sqlite3_get_table()執(zhí)行語(yǔ)句:
select * from student
實(shí)現(xiàn)代碼如下:
void do_show_sample(sqlite3 *db)
{
char **result, *errmsg;
int nrow, ncolumn, i, j, index;
if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
{
printf("error : %s\n", errmsg);
sqlite3_free(errmsg);
}
index = ncolumn;
for (i=0; i<nrow; i++)
{
for (j=0; j<ncolumn; j++)
{
printf("%-8s : %-8s\n", result[j], result[index]);
index++;
}
printf("************************\n");
}
sqlite3_free_table(result);
return;
}
假定當(dāng)前的表格的數(shù)據(jù)信息如下:
關(guān)于這個(gè)函數(shù)中出現(xiàn)的這些參數(shù)的具體含義,我們可以見(jiàn)下圖:
sqlite3編程接口非常多,對(duì)于初學(xué)者來(lái)說(shuō),我們暫時(shí)只需要掌握常用的幾個(gè)函數(shù),其他函數(shù)自然就知道如何使用了。
數(shù)據(jù)庫(kù)
本篇假設(shè)數(shù)據(jù)庫(kù)為my.db,有數(shù)據(jù)表student。
創(chuàng)建表格語(yǔ)句如下:
CREATE TABLE IF NOT EXISTS student (no integer primary key, name text, score real);
常用函數(shù)
sqlite3_open
int sqlite3_open(char *path, sqlite3 **db);
功能: 打開(kāi)sqlite數(shù)據(jù)庫(kù)
參數(shù):
path: 數(shù)據(jù)庫(kù)文件路徑
db: 指向sqlite句柄的指針
返回值: 成功返回0,失敗返回錯(cuò)誤碼(非零值)
sqlite3_close
int sqlite3_close(sqlite3 *db);
功能: 關(guān)閉sqlite數(shù)據(jù)庫(kù)
返回值: 成功返回0,失敗返回錯(cuò)誤碼
const char *sqlite3_errmsg(sqlite3 *db);
功能: 打印錯(cuò)誤信息
返回值: 返回錯(cuò)誤信息
不使用回調(diào)函數(shù)執(zhí)行SQL語(yǔ)句
sqlite3_get_table
int sqlite3_get_table(sqlite3 *db, const char *sql, char ***resultp, int*nrow, int *ncolumn, char **errmsg);
功能:
執(zhí)行SQL操作
參數(shù):
db:數(shù)據(jù)庫(kù)句柄
sql:SQL語(yǔ)句
resultp:用來(lái)指向sql執(zhí)行結(jié)果的指針
nrow:滿足條件的記錄的數(shù)目
ncolumn:每條記錄包含的字段數(shù)目
errmsg:錯(cuò)誤信息指針的地址
返回值:
成功返回0,失敗返回錯(cuò)誤碼
舉例
下面比如我們要顯示student表中所有的數(shù)據(jù)信息,我們就可以利用sqlite3_get_table()執(zhí)行語(yǔ)句:
select * from student
實(shí)現(xiàn)代碼如下:
void do_show_sample(sqlite3 *db)
{
char **result, *errmsg;
int nrow, ncolumn, i, j, index;
if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
{
printf("error : %s\n", errmsg);
sqlite3_free(errmsg);
}
index = ncolumn;
for (i=0; i<nrow; i++)
{
for (j=0; j<ncolumn; j++)
{
printf("%-8s : %-8s\n", result[j], result[index]);
index++;
}
printf("************************\n");
}
sqlite3_free_table(result);
return;
}
假定當(dāng)前的表格的數(shù)據(jù)信息如下:
關(guān)于這個(gè)函數(shù)中出現(xiàn)的這些參數(shù)的具體含義,我們可以見(jiàn)下圖:
在這里插入圖片描述
由上圖可知:代碼中:
ncolumn = 3nrow = 5result 指向所有的結(jié)果組成的字符串?dāng)?shù)組,各個(gè)具體字符串的下標(biāo),圖上已經(jīng)標(biāo)明。
結(jié)合此圖再去理解代碼,就很容易理解代碼的實(shí)現(xiàn)原理。
使用回調(diào)函數(shù)執(zhí)行SQL語(yǔ)句
sqlite3_exec
typedef int (*sqlite3_callback)(void *, int, char **, char **);
int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *, char **errmsg);
功能:
執(zhí)行SQL操作
參數(shù):
db:數(shù)據(jù)庫(kù)句柄
sql:SQL語(yǔ)句,就是我們前面兩章用于操作表的增刪改查語(yǔ)句
callback:回調(diào)函數(shù)
errmsg:錯(cuò)誤信息指針的地址
返回值:
成功返回0,失敗返回錯(cuò)誤碼
回調(diào)函數(shù)
typedef int (*sqlite3_callback)(void *para, int f_num, char **f_value, char **f_name);
功能:
每找到一條記錄自動(dòng)執(zhí)行一次回調(diào)函數(shù)
參數(shù):
para:傳遞給回調(diào)函數(shù)的參數(shù)
f_num:記錄中包含的字段數(shù)目
f_value:包含每個(gè)字段值的指針數(shù)組
f_name:包含每個(gè)字段名稱(chēng)的指針數(shù)組
返回值:
成功返回0,失敗返回-1
舉例
sqlite3 *db;
char *errmsg,**resultp;
int callback(void *para, int f_num, char **f_val, char **f_name)
{
int i;
for (i=0; i<f_num; i++)
{
printf("%-8s", f_val[i]);
}
printf("\n");
return 0;
}
void do_show(sqlite3 *db)
{
char *errmsg;
printf("no name score\n");
if (sqlite3_exec(db, "select * from student", callback, NULL, &errmsg) != 0)
{
printf("error : %s\n", sqlite3_errmsg(db));
}
printf("\n");
return;
}
回調(diào)函數(shù)方法實(shí)現(xiàn)的代碼,需要實(shí)現(xiàn)一個(gè)回調(diào)函數(shù):callback。函數(shù)sqlite3_exec()在解析命令"select * from student" ,沒(méi)獲取到一行數(shù)據(jù)就會(huì)調(diào)用一次回調(diào)函數(shù), 參考上面的表格student,
callback()總共會(huì)被調(diào)用5次,
f_num 對(duì)應(yīng)結(jié)果的列數(shù),為3
f_value 則指向 每一列對(duì)應(yīng)的值組成的字符串?dāng)?shù)組
假設(shè)現(xiàn)在callback是第四次被調(diào)用,如下圖:
運(yùn)行結(jié)果
編譯需要使用第三方庫(kù)lsqlite3。
gcc student.c -o run -lsqlite3
其他函數(shù)
sqlite3 *pdb, 數(shù)據(jù)庫(kù)句柄,跟文件句柄FILE很類(lèi)似
sqlite3_stmt *stmt, 這個(gè)相當(dāng)于ODBC的Command對(duì)象,用于保存編譯好的SQL語(yǔ)句
sqlite3_exec(), 執(zhí)行非查詢(xún)的sql語(yǔ)句
sqlite3_prepare(), 準(zhǔn)備sql語(yǔ)句,執(zhí)行select語(yǔ)句或者要使用parameter bind時(shí),用這個(gè)函數(shù)(封裝了sqlite3_exec)
Sqlite3_step(), 在調(diào)用sqlite3_prepare后,使用這個(gè)函數(shù)在記錄集中移動(dòng)
還有一系列的函數(shù),用于從記錄集字段中獲取數(shù)據(jù),如
sqlite3_column_text(), 取text類(lèi)型的數(shù)據(jù)
sqlite3_column_blob(),取blob類(lèi)型的數(shù)據(jù)
sqlite3_column_int(), 取int類(lèi)型的數(shù)據(jù)
國(guó)際慣例,上完整代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sqlite3.h>
void do_insert(sqlite3 *db)
{
int no;
char name[16];
float score;
char sqlstr[128], *errmsg;
printf("input no : ");
scanf("%d", &no);
printf("input name : ");
scanf("%s", name);
printf("input score : ");
scanf("%f", &score);
sprintf(sqlstr, "insert into student values (%d, '%s', %.1f)",
no, name, score);
#if __DEBUG
printf("cmd:%s\n",sqlstr);
#endif
if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != 0)
{
printf("error : %s\n", sqlite3_errmsg(db));
}
else
{
printf("insert is done\n");
}
printf("\n");
return;
}
void do_delete(sqlite3 *db)
{
char *errmsg;
char sqlstr[128], expression[64];
printf("input expression : ");
scanf("%s", expression);//name='ma'
sprintf(sqlstr, "delete from student where %s", expression);
#if __DEBUG
printf("cmd:%s\n",sqlstr);
#endif
if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != 0)
{
printf("error : %s\n", sqlite3_errmsg(db));
}
else
{
printf("deletet is done\n");
}
printf("\n");
return;
}
int callback(void *para, int f_num, char **f_val, char **f_name)
{
int i;
for (i=0; i<f_num; i++)
{
printf("%-8s", f_val[i]);
}
printf("\n");
return 0;
}
void do_show(sqlite3 *db)
{
char *errmsg;
printf("no name score\n");
if (sqlite3_exec(db, "select * from student", callback, NULL, &errmsg) != 0)
{
printf("error : %s\n", sqlite3_errmsg(db));
}
printf("\n");
return;
}
void do_show_sample(sqlite3 *db)
{
char **result, *errmsg;
int nrow, ncolumn, i, j, index;
if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
{
printf("error : %s\n", errmsg);
sqlite3_free(errmsg);
}
index = ncolumn;
for (i=0; i<nrow; i++)
{
for (j=0; j<ncolumn; j++)
{
printf("%-8s : %-8s\n", result[j], result[index]);
index++;
}
printf("************************\n");
}
sqlite3_free_table(result);
return;
}
int main()
{
sqlite3 *db;
int n;
char clean[64];
if (sqlite3_open("my.db", &db) < 0)
{
printf("fail to sqlite3_open : %s\n", sqlite3_errmsg(db));
return -1;
}
while ( 1 )
{
printf("*********************************************\n");
printf("1: insert record \n2: delete record \n3: show record \n4: quit\n");
printf("*********************************************\n");
printf("please select : ");
if (scanf("%d", &n) != 1)
{
fgets(clean, 64, stdin);
printf("\n");
continue;
}
switch ( n )
{
case 1 :
do_insert(db);
break;
case 2 :
do_delete(db);
break;
case 3 :
do_show_sample(db);
break;
case 4 :
sqlite3_close(db);
exit(0);
}
}
return 0;
}
運(yùn)行主頁(yè)面:
插入記錄:
顯示記錄:
刪除記錄:
End