嵌入式環境下使用SQLite
阿新 • • 發佈:2018-12-18
環境搭建
下載SQLite的原始碼,https://www.sqlite.org/download.html,下載名為sqlite-autoconf的包,在交叉編譯環境下(我的是Ubuntu系統)使用arm編譯器進行編譯。
# 將包內的檔案提取出來,假定提取後的資料夾名為sqlite-autoconf-3250200 # cd到此目錄,使用./configure --host=arm-arago-linux-gnueabi --prefix=/home/root/Desktop/sqlite/build PS:我的交叉編譯工具鏈中gcc全名為arm-arago-linux-gnueabi-gcc,所以host就填寫為arm-arago-linux-gnueabi,configure用到的gcc、g++、strip等都會以arm-arago-linux-gnueabi為字首自動引用到。prefix就是生成的so和標頭檔案的路徑,可以自己定義 # 等待configure完成後,執行make && make install # make完成後將build目錄下,lib資料夾中的檔案拷貝到開發板系統中的/lib目錄下,將bin中的檔案拷貝到開發板系統的/bin目錄下 # 在開發板系統中執行sqlite3 test.db命令,如果可以執行成功,則說明移植成功,執行成功出現 SQLite version 3.25.2 2018-09-25 15:08:22 Enter ".help" for usage hints. sqlite> 我第一次執行並沒有成功,因為依賴libreadline.so.5,既然能編譯成功,說明交叉編譯環境中是有這個庫的,使用locate libreadline查詢庫的位置,並拷貝到開發板系統的/lib目錄下。 注意:如果出現了多個libreadline庫的位置,需要拷貝交叉編譯器目錄下的庫,不能使用當前系統中的libreadline庫。我的libreadline庫位置在/usr/local/arm/cross/am335xt3/devkit/arm-arago-linux-gnueabi/usr/lib/下,大家根據自己的環境查詢。 # 開發板的環境搭建好了,還需要將生成的build/lib目錄下的檔案拷貝一份到交叉編譯器的lib下,使之可以編譯c/c++程式碼成功,並且將build/include目錄下的標頭檔案拷貝到交叉編譯器的include目錄下,我的include目錄在/usr/local/arm/cross/am335xt3/devkit/arm-arago-linux-gnueabi/usr/include # 這時,交叉編譯環境下的sqlite也搭建好了,注意編譯時需要連結sqlite3庫,例如arm-arago-linux-gnueabi-gcc test.c -lsqlite3
示例程式碼
建立表、插入表項
#include <stdio.h>
#include <sqlite3.h>
int main( void )
{
sqlite3 *db=NULL;
char *error_msg = NULL;
int ret = 0;
char *sql;
//開啟資料庫檔案,如果不存在將建立一個數據庫檔案
sqlite3_initialize();
ret = sqlite3_open_v2("test.db", &db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL);
if ( ret )
{
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
//建立表,如果表存在,則不建立,並給出提示資訊,儲存在 error_msg 中
//表中只有一個自增鍵 每次插入自動+1
sql = "CREATE TABLE test_table(\
ID INTEGER PRIMARY KEY, \
);";
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
//插入資料
sql = "INSERT INTO \"test_table\" VALUES(null);" ;
//執行sql語句
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_exec( db, sql, 0, 0, &zErrMsg );
sqlite3_close_v2(db); //關閉資料庫
sqlite3_shutdown();
return 0;
}
查詢表項
接上邊的插入好的資料庫檔案
#include <stdio.h>
#include <sqlite3.h>
int main()
{
sqlite3 *db = NULL;
char *error_msg = NULL;
int ret = 0;
sqlite3_initialize();
ret = sqlite3_open_v2("test.db", &db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL);
if( ret )
{
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
char **table_array;
int nrow,ncolumn;
int i,j,index;
ret = sqlite3_get_table(db,"SELECT * FROM test_table",&table_array,&nrow,&ncolumn,&error_msg);
if(ret == SQLITE_OK)
{
index = 0;
//列印列名 此例只有一項“ID”
printf("%s\n",table_array[index++]);
for(i=0;i<nrow;i++)
{
for(j=0;j<ncolumn;j++)
{
printf("%s\n",table_array[index++]);
}
printf("\n");
}
sqlite3_free_table(table_array);
}
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
刪除表項
#include <stdio.h>
#include <sqlite3.h>
int main()
{
sqlite3 *db = NULL;
char *sql = NULL;
char *error_msg = NULL;
int ret = 0;
sqlite3_initialize();
ret = sqlite3_open_v2("test.db", &db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL);
if( ret )
{
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
//刪除ID為5的表項
sql = "DELETE FROM test_table where ID = 5";
//刪除按ID排序的前三項
//sql = "DELETE FROM test_table where ID in(SELECT * FROM test_table order by ID limit 3)";
//刪除表中全部內容
//sql = "DELETE FROM test_table;"
int ret = sqlite3_exec(db,sql,0,0,&error_msg);
if(ret == SQLITE_OK)
{
//作用是重新構建資料庫檔案,回收空白空間,減小資料庫檔案的大小。
sqlite3_exec(db,"VACUUM;",0,0,&error_msg);
}
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
工作需求
在開發板中插入SD卡存放資料庫檔案來儲存資料,以實現方便快捷的增刪改查,要求SD卡滿了將早期資料刪除再存放新插入的資料。但是經過測試,SD卡滿了以後再刪除資料就會報錯,會提示database or disk is full。
-
解決方案
每次插入資料時檢查一次SD卡空間,當SD卡佔用達到一定程度(暫定80%)時,進行一次早期資料刪除。
#include <stdio.h>
#include <sys/vfs.h>
#include <sqlite3.h>
int check_space();
int free_some_space();
int main(void)
{
sqlite3 *db = NULL;
char *error_msg = NULL;
int ret = 0;
char *sql;
//開啟資料庫檔案,如果不存在將建立一個數據庫檔案
sqlite3_initialize();
ret = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (ret)
{
sqlite3_close_v2(db);
sqlite3_shutdown();
return 0;
}
//建立表,如果表存在,則不建立,並給出提示資訊,儲存在 error_msg 中
//表中只有一個自增鍵 每次插入自動+1
sql = "CREATE TABLE test_table(\
ID INTEGER PRIMARY KEY, \
);";
sqlite3_exec(db, sql, 0, 0, &zErrMsg);
//插入資料
sql = "INSERT INTO \"test_table\" VALUES(null);";
//執行sql語句
while (1)
{
//SD卡佔用空間達到80%時 刪除一些早期的資料 釋放空間
if (check_space() == -1)
{
ret = free_some_space(db);
if (ret != SQLITE_OK)
{
printf("error code is %d\n", ret);
goto End;
}
}
ret = sqlite3_exec(db, sql, 0, 0, &error_msg);
printf("ret: %d msg: %s\n", ret, error_msg);
}
End:
sqlite3_close_v2(db); //關閉資料庫
sqlite3_shutdown();
return 0;
}
int check_space()
{
struct statfs sfs;
statfs("/media/mmcblk0p1", &sfs);
int percent = (sfs.f_blocks - sfs.f_bfree) * 100 / (sfs.f_blocks - sfs.f_bfree + sfs.f_bavail) + 1;
//SD卡佔用空間達到80%時 返回-1
if (percent > 80)
return -1;
return 0;
}
int free_some_space()
{
char *sql = ;
char *error_msg = "DELETE FROM test_table where ID in(SELECT * FROM test_table order by ID limit 20);";
int ret = sqlite3_exec(db, sql, 0, 0, &error_msg);
if (ret == SQLITE_OK)
{
//重新構建資料庫檔案,回收空白空間,減小資料庫檔案的大小。
ret = sqlite3_exec(db, "VACUUM;", 0, 0, &error_msg);
}
return ret;
}