嵌入式數據庫介紹
隨着電子技術的飛速發展,嵌入式系統中的存儲器容量和性能也在迅速提高,這爲擴大嵌入式的應用領域提供了必要的物理基礎。展望未來,嵌入式系統正在向網絡化、智能化等高端應用方向發展。在這個發展過程中,嵌入式系統內的數據量會急劇膨脹。因此,嵌入式數據庫的作用將會變得越來越重要。
由於嵌入式平臺和應用領域的多樣化,所以嵌入式數據庫的體系結構與運行模式和企業級數據庫有很大的區別。嵌入式數據庫的主要特性如下:
(1)嵌入性
嵌入性是嵌入式數據庫的根本特性。嵌入式數據庫不但可以嵌入到各種軟件中,也能嵌入到硬件中。
(2)可移植性
可移植性是嵌入性的基本保證。嵌入式數據庫必須能夠支持各種硬件平臺。
(3)實時性
在嵌入式領域,實時性是一個重要的指標。所以嵌入式數據庫也需要具有較高的實時性能。
(4)伸縮性
伸縮性使嵌入式數據庫能夠滿足各種應用需要,提高嵌入式系統的性能。
(5)可移動性
隨着嵌入式系統的網絡化發展,可移動性也正變得越來越重要。所以嵌入式數據庫需要滿足可移動性的要求。
爲了更好的滿足嵌入式應用的需求,嵌入式數據庫本身需要具有企業級數據庫的基本功能(比如一致性、安全性等)。此外,嵌入式數據庫也必須提供一套完整的SQL接口,以滿足應用開發的需要。
總而言之,嵌入式數據庫的應用環境是非常苛刻的。嵌入式數據庫需要在滿足應用要求的前提下保證高效的運行性能。
根據應用方式的不同,嵌入式數據庫可以大致分爲以下幾類:
(1)C/S嵌入式數據庫
C/S嵌入式數據庫可以看成是企業級數據庫的一個精簡版,一般運用在對實時性要求不高的系統中。
(2)面向軟件嵌入式數據庫
面向軟件嵌入式數據庫以組件的形式嵌入到軟件中,一般運用在對運行速度和安全性要求較高的系統中。
(3)面向硬件嵌入式數據庫
面向硬件嵌入式數據庫直接嵌入到硬件設備中,一般運用在對實時性和穩定性要求較高的系統中。
(4)內存嵌入式數據庫
內存嵌入式數據庫直接運行在內存中,所以運行性能非常高。但數據無法永久保存。
2. SQLite介紹
SQLite是一款輕量級的開源嵌入式數據庫,由D.Richard Hipp在2000年發佈。SQLite使用方便,性能出衆,廣泛應用於消費電子、醫療、工業控制、軍事等各種領域。SQLite主要具有以下特點:
l 性能:SQLite對數據庫的訪問性能很高,其運行速度比Mysql、PostgreSQL等開源數
據庫要快很多。
l 體積:SQLite的體積非常小巧,最低只需要幾百K的內存就可以運行。
l 可移植性:SQLite的能支持各種32位和64位體系的硬件平臺,也能在Windows、Linux、
BSD、Mac OS、Solaries等軟件平臺中運行。
l 穩定性:SQLite支持事務的ACID特性,既原子性、一致性、隔離性、持久性
l SQL支持:SQLite支持ANSI SQL92中的大多數標準,提供了對子查詢、視圖、觸發
器等機制的支持。
l 接口:SQLite爲C、Java、PHP、Python、Tcl等多種語言提供了API接口。
SQLite總體採用了模塊化設計
(1)接口。接口由SQLite C API函數組成。所有的應用程序都必須通過接口訪問SQLite數據庫。
(2)編譯器。編譯器由詞法分析、語法分析和中間代碼生成三個模塊組成。其中,詞法分析模塊和語法分析模塊負責檢查SQL語句的語法,然後把生成的語法樹傳遞給中間代碼生成模塊。中間代碼生成模塊負責生成SQLite引擎可以識別的中間代碼。
(3)數據庫引擎。數據庫引擎是SQLite的核心,負責運行中間代碼,指揮數據庫的具體操作。
(4)後臺。後臺由B樹、頁緩存和系統調用三個模塊組成。其中,B樹負責維護索引,頁緩存負責頁面數據的傳送,系統調用負責和操作系統交互,最終實現數據庫的訪問。
11.2 SQLite3的使用
11.2.1 SQLite3的命令
SQLite3是目前最新的SQLite版本。可以從http://www.sqlite.org/download.html網站上下載SQLite3的源代碼。
解壓縮後進入sqlite-3.6.12的根目錄,首先命令“./configure”生成Makefile文件,接着運行命令“make”對源代碼進行編譯,最後運行命令“make install”安裝SQLite3。安裝完畢後,可以運行命令sqlite3查看SQLite3是否能正常運行,如下所示:
[root@localhost ~]#sqlite3
SQLite version 3.6.12
Enter".help" for instructions
Enter SQLstatements terminated with a ";"
sqlite>
可以看到,SQLite3啓動後會停留在提示符sqlite>處,等待用戶輸入SQL語句。
在使用SQLite3前需要先了解下SQLite3支持的數據類型。SQLite3支持的基本數據類型主要有以下幾類:
l NULL
l NUMERIC
l INTEGER
l REAL
l TEXT
SQLite3會自動把其他數據類型轉換成以上5類基本數據類型,轉換規則如下所示:
l char、clob、test、varchar—> TEXT
l integer—>INTEGER
l real、double、float—> REAL
l blob—>NULL
l 其餘數據類型都轉變成NUMERIC
下面通過一個實例來演示SQLite3的使用方法。
(1) 新建一個數據庫
新建數據庫test.db(使用.db後綴是爲了標識數據庫文件)。在test.db中新建一個表test_table,該表具有name,、sex、age三列。SQLite3的具體操作如下所示:
[root@localhosthome]# sqlite3 test.db
SQLite version 3.6.12
Enter".help" for instructions
Enter SQLstatements terminated with a ";"
sqlite>create table test_table(name, sex, age);
如果數據庫test.db已經存在,則命令“sqlite3 test.db”會在當前目錄下打開test.db。如果數據庫test.db不存在,則命令“sqlite3 test.db”會在當前目錄下新建數據庫test.db。爲了提高效率,SQLite3並不會馬上創建test.db,而是等到第一個表創建完成後纔會在物理上創建數據庫。
由於SQLite3能根據插入數據的實際類型動態改變列的類型,所以在create語句中並不要求給出列的類型。
(2) 創建索引
爲了加快表的查詢速度,往往在主鍵上添加索引。如下所示的是在name列上添加索引的過程。
sqlite>create index test_index on test_table(name);
(3) 操作數據
如下所示的是在test_table中進行數據的插入、更新、刪除操作:
sqlite>insert into test_table values ('xiaoming', 'male', 20);
sqlite>insert into test_table values ('xiaohong', 'female', 18);
sqlite>select * from test_table;
xiaoming|male|20
xiaohong|female|18
sqlite>update test_table set age=19 where name = 'xiaohong';
sqlite>select * from test_table;
xiaoming|male|20
xiaohong|female|19
sqlite>delete from test_table where name = 'xiaoming';
sqlite>select * from test_table;
xiaohong|female|19
(4) 批量操作數據庫
如下所示的是在test_table中連續插入兩條記錄:
sqlite> begin;
sqlite>insert into test_table values ('xiaoxue', 'female', 18);
sqlite>insert into test_table values ('xiaoliu', 'male', 20);
sqlite> commit;
sqlite>select * from test_table;
xiaohong|female|19
xiaoxue|male|18
xiaoliu|male|20
運行命令commit後,纔會把插入的數據寫入數據庫中。
(5) 數據庫的導入導出
如下所示的是把test.db導出到sql文件中:
[root@localhosthome]# sqlite3 test.db ".dump" > test.sql;
test.sql文件的內容如下所示:
BEGINTRANSACTION;
CREATE TABLEtest_table(name, sex, age);
INSERT INTO"test_table" VALUES('xiaohong','female',19);
CREATE INDEXtest_index on test_table(name);
COMMIT;
如下所示的是導入test.sql文件(導入前刪除原有的test.db):
[root@localhosthome]# sqlite3 test.db < test.sql;
通過對test.sql文件的導入導出,可以實現數據庫文件的備份。
11.2.2 SQLite3的C接口
以上介紹的是SQLite3數據庫的命令操作方式。在實際使用中,一般都是應用程序需要對數據庫進行訪問。爲此,SQLite3提供了各種編程語言的使用接口(本書介紹C語言接口)。SQLite3具有幾十個C接口,下面介紹一些常用的C接口。
l sqlite_open
作用:打開SQLite3數據庫
原型:int sqlite3_open(const char *dbname, sqlite3 **db)
參數:
dbname:數據庫的名稱;
db:數據庫的句柄;
返回值:返回值的具體含義如表11-1所示:
表11-1
返回值 |
標識符 |
含義 |
0 |
SQLITE_OK |
操作成功 |
1 |
SQLITE_ERROR |
操作失敗 |
2 |
SQLITE_INTERNAL |
內部邏輯錯誤 |
3 |
SQLITE_PERM |
訪問權限錯誤 |
4 |
SQLITE_ABORT |
操作異常 |
5 |
SQLITE_BUSY |
數據庫被鎖定 |
6 |
SQLITE_LOCKED |
表被鎖定 |
7 |
SQLITE_NOMEM |
內存申請失敗 |
8 |
SQLITE_READONLY |
寫只讀數據庫 |
9 |
SQLITE_INTERRUPT |
內部中斷 |
10 |
SQLITE_IOERR |
I/O錯誤 |
11 |
SQLITE_CORRUPT |
數據庫鏡像格式錯誤 |
12 |
SQLITE_NOTFOUND |
找不到文件或數據 |
13 |
SQLITE_FULL |
數據庫已滿 |
14 |
SQLITE_CANTOPEN |
無法打開數據庫文件 |
15 |
SQLITE_PROTOCOL |
鎖協議出錯 |
16 |
SQLITE_EMPTY |
表爲空 |
17 |
SQLITE_SCHEMA |
數據庫體系發生改變 |
18 |
SQLITE_TOOBIG |
記錄數據溢出 |
19 |
SQLITE_CONSTRAINT |
違反約束產生異常 |
20 |
SQLITE_MISMATCH |
數據類型不匹配 |
21 |
SQLITE_MISUSE |
數據庫使用不正確 |
22 |
SQLITE_NOLFS |
系統不支持 |
23 |
SQLITE_AUTH |
未獲授權 |
100 |
SQLITE_ROW |
sqlite_step() |
101 |
SQLITE_DONE |
sqlite_step()結束運行 |
l sqlite_colse
作用:關閉SQLite3數據庫
原型:int sqlite_close(sqlite3 *db)
例如:
l test.c:
#include <stdio.h>
#include <sqlite3.h>
static sqlite3 *db=NULL;
int main()
{
int rc;
rc= sqlite3_open("test.db", &db);
if(rc)
{
printf("can't open database!\n");
}
else
{
printf("open database success!\n");
}
sqlite3_close(db);
return 0;
}
運行命令“gcc –o test test.c –lsqlite3”進行編譯,運行test的結果如下所示:
[root@localhosthome]# open database success!
l sqlite_exec
作用:執行SQL語句
原型:int sqlite3_exec(sqlite3 *db, const char *sql, int(*callback)(void*,int,char**,char**), void *, char **errmsg)
參數:
db:數據庫;
sql:SQL語句;
callback:回滾;
errmsg:錯誤信息
例如:
l test.c:
#include <stdio.h>
#include <sqlite3.h>
static sqlite3 *db=NULL;
static char *errmsg=NULL;
int main()
{
int rc;
rc = sqlite3_open("test.db", &db);
rc = sqlite3_exec(db,"insert into test_table values('daobao','male', 24)", 0, 0, &errmsg);
if(rc)
{
printf("exec fail!\n");
}
else
{
printf("exec success!\n");
}
sqlite3_close(db);
return 0;
}
編譯完成後,運行test的結果如下所示:
[root@localhosthome]# ./test
exec success!
[root@localhosthome]# sqlite3 test.db
SQLite version 3.6.11
Enter".help" for instructions
Enter SQLstatements terminated with a ";"
sqlite>select * from test_table;
daobao|male|24
l sqlite3_get_table
作用:執行SQL查詢
原型:int sqlite3_get_table(sqlite3 *db, const char *zSql, char***pazResult, int *pnRow, int *pnColumn,char **pzErrmsg)
參數:
db:數據庫;
zSql:SQL語句;
pazResult:查詢結果集;
pnRow:結果集的行數;
pnColumn:結果集的列數;
errmsg:錯誤信息;
l sqlite3_free_table
作用:註銷結果集
原型:void sqlite3_free_table(char **result)
參數:
result:結果集;
例如:
l test.c:
#include <stdio.h>
#include <sqlite3.h>
static sqlite3 *db=NULL;
static char **Result=NULL;
static char *errmsg=NULL;
int main()
{
int rc, i, j;
int nrow;
int ncolumn;
rc= sqlite3_open("test.db", &db);
rc= sqlite3_get_table(db, "select * from test_table",&Result, &nrow, &ncolumn,
&errmsg);
if(rc)
{
printf("query fail!\n");
}
else
{
printf("query success!\n");
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
printf("%s | ", Result[i* ncolumn + j]);
}
printf("\n");
}
}
sqlite3_free_table(Result);
sqlite3_close(db);
return 0;
}
編譯完成後,運行test的結果如下所示:
[root@localhosthome]# ./test
query success!
xiaohong |female | 19 |
xiaoxue | female| 18 |
xiaoliu | male |20 |
daobao | male |24 |
l sqlite3_prepare
作用:把SQL語句編譯成字節碼,由後面的執行函數去執行
原型:int sqlite3_prepare(sqlite3 *db, const char *zSql, int nByte,sqlite3_stmt **stmt, const char **pTail)
參數:
db:數據庫;
zSql:SQL語句;
nByte:SQL語句的最大字節數;
stmt:Statement句柄;
pTail:SQL語句無用部分的指針;
l sqlite3_step
作用:步步執行SQL語句字節碼
原型:int sqlite3_step (sqlite3_stmt *)
例如:
l test.c:
#include<stdio.h>
#include<sqlite3.h>
static sqlite3 *db=NULL;
static sqlite3_stmt *stmt=NULL;
int main()
{
int rc, i, j;
int ncolumn;
rc= sqlite3_open("test.db",&db);
rc=sqlite3_prepare(db,"select * fromtest_table",-1,&stmt,0);
if(rc)
{
printf("query fail!\n");
}
else
{
printf("query success!\n");
rc=sqlite3_step(stmt);
ncolumn=sqlite3_column_count(stmt);
while(rc==SQLITE_ROW)
{
for(i=0; i<2; i++)
{
printf("%s | ",sqlite3_column_text(stmt,i));
}
printf("\n");
rc=sqlite3_step(stmt);
}
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
編譯完成後,運行test的結果如下所示:
[root@localhosthome]# ./test
query success!
xiaohong |female | 19 |
xiaoxue | female| 18 |
xiaoliu | male |20 |
daobao | male |24 |
在程序中訪問SQLite3數據庫時,要注意C API的接口定義和數據類型是否正確,否則會得到錯誤的訪問結果。