嵌入式資料庫SQLite的編譯、安裝和使用
下文介紹的内容都是基于 RedHat Linux 9.0 平台的。
引言:sqlite簡介
sqlite是嵌入式SQL資料庫引擎SQLite(SQLite Embeddable SQL Database Engine)的一個擴充。
SQLite是一個實作嵌入式SQL資料庫引擎小型C語言庫(C library),實作了獨立的,可嵌入的,零配置的SQL資料庫引擎。
特性包括:事務操作是原子,一緻,孤立,并且持久的,即使在系統崩潰和電源故障之後。零配置——不需要安裝和管理。
實作了絕大多數SQL92标準。整個資料庫存儲在一個單一的檔案中。資料庫檔案可以在不同位元組序的機器之間自由地共享。
支援最大可達2T的資料庫。字元串和BLOB類型的大小隻受限于可用記憶體。完整配置的少于250KB,忽略一些可選特性的少于150KB。
在大多數常見操作上比流行的客戶/伺服器資料庫引擎更快。 簡單易于使用的API。 内建TCL綁定。
另外提供可用于許多其他語言的綁定。具有良好注釋的源代碼,代碼95%有較好的注釋。
獨立:沒有外部依賴。源代碼位于公共域,可用于任何用途。
用 SQLite連接配接的程式可以使用SQL資料庫,但不需要運作一個單獨的關系型資料庫管理系統程序(separate RDBMS process)。
SQLite不是一個用于連接配接到大型資料庫伺服器(big database server)的用戶端庫(client library),
而是非常适合桌面程式和小型網站的資料庫伺服器。SQLite直接讀寫(reads and writes directly)在硬碟上的資料庫檔案。
本文将告訴你怎麼開始體驗 SQLite ,這裡沒有長長的說明和冗煩的配置。
一、sqlite-3.3.8編譯安裝
請閱讀在安裝包裡的 INSTALL或者README 檔案。SQLite已經内置了,你不需要安裝任何附加的軟體(additional software)。
Windows users可以下載下傳SQLite擴充DLL。
這裡簡單介紹一下:
假設你得到的是源代碼sqlite-3.3.8.tar.gz,這裡将告訴你怎麼編譯它。
解壓sqlite-3.3.8.tar.gz 到 /home目錄下
For example:
tar zxvf sqlite-3.3.8.tar.gz -C /home
cd /home
mkdir sqlite-3.3.8-ix86
cd /home/sqlite-3.3.8-ix86/
../sqlite-3.3.8/configure --prefix=/home/sqlite-3.3.8-ix86
編譯并安裝,然後生成幫助文檔
make && make install && make doc
如果出現下列錯誤
../sqlite-3.3.8/src/tclsqlite.c: In function `DbUpdateHandler':
../sqlite-3.3.8/src/tclsqlite.c:333: warning: passing arg 3 of `Tcl_ListObjAppendElement' makes pointer from integer without a cast
../sqlite-3.3.8/src/tclsqlite.c: In function `tclSqlFunc':
../sqlite-3.3.8/src/tclsqlite.c:419: warning: passing arg 1 of `Tcl_NewByteArrayObj' discards qualifiers from pointer target type
...
這個都是tcl相關的錯誤,可以先安裝ActiveTcl以解決.假如你不需要tcl支援,那麼這個錯誤可以這樣避免:
cd /home/sqlite-3.3.8-ix86/
../sqlite-3.3.8/configure --disable-tcl --prefix=/home/sqlite-3.3.8-ix86
編譯并安裝,然後生成幫助文檔
make && make install && make doc
不出意外,将不會出現錯誤,那麼
Libraries have been installed in:
/home/sqlite-3.3.8-ix86/lib
庫檔案已經生成在 /home/sqlite-3.3.8-ix86/lib 目錄下
可執行檔案sqlite3已經生成在 /home/sqlite-3.3.8-ix86/bin 目錄下
下面建立一個新的資料庫檔案名叫"zieckey.db" (當然你可以使用不同的名字) 來測試資料庫.
直接輸入: /home/sqlite-3.3.8-ix86/bin/sqlite3 test.db
如果出現下面字樣表明編譯安裝已經成功了.
SQLite version 3.3.8
Enter ".help" for instructions
sqlite>
二 、SQLite的基本文法
這一章我們将會學習到sqlite的基本文法,sqlite的文法現象和SQL92是比較相象的,
或者說sqlite3相容大部份SQL92的文法現象。
下面我們看看怎麼用這些文法現象來建立資料庫以及對資料庫的各種操作。
2.1 建立一個資料庫
例如我們想建立一個資料庫命名為zieckey.db ,可以直接在shell下輸入 sqlite3 zieckey.db ,
前提是:先進放sqlite的安裝檔案夾下然後執行下面的操作:
# ./sqlite3 zieckey.db
SQLite version 3.0.8
Enter ".help" for instructions
sqlite>
這裡 SQLite version 3.0.8 是SQLite的版本資訊。也就是說本文使用的sqlite版本為 version 3.0.8 .
這樣就建立了一個新的資料庫檔案,命名為 zieckey.db
2.2 建立表和插入值
剛剛我們建立了一個新的資料庫zieckey.db,加入我們想在其中建立一個名為 SensorData 的表,其包含五個列元素。
可以用CREATE TABLE文法指令。
CREATE TABLE語句基本上就是"CREATE TABLE"關鍵字後跟一個新的表名以及括号内的一堆定義和限制。表名可以是字元串或者辨別符。以"sqlite_"開頭的表名是留給sqlite資料庫引擎使用的。每個字段的定義是字段名後跟字段的資料類型,接着是一個或多個的字段限制。字段的 資料類型并不限制字段中可以存放的資料。更多資訊,參見sqlite的CREATE TABLE文法。
這裡具體作法如下:
# sqlite3 zieckey.db
SQLite version 3.0.8
Enter ".help" for instructions
sqlite> CREATE TABLE SensorData(
...> ID INTEGER PRIMARY KEY,
...> SensorID INTEGER,
...> SiteNum INTEGER,
...> Time VARCHAR(12),
...> SensorParameter REAL
...> );
注意sqlite下除了特殊指令都要以分号 “;” 結尾,否則它将一直等待第一個分号的出現才判斷這條指令結束。
現在我們可以用 schema 指令看看我們剛剛建立的表。具體作法如下:
sqlite> .schema
CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);
sqlite>
.schema 是用來檢視資料庫中所有的表的定義内容。如果後面跟了具體的表名稱,則顯示該表的内容。
假如我們想想SensorData表中插入具體列元素值,該怎麼辦呢?這裡可以用INSERT語句。
INSERT語句有兩種基本形式。一種帶有"VALUES"關鍵字,在已有表中插入一個新的行。若不定義字段清單,那麼值的數目将與表中的字段數目相同。否則值的數目須與字段清單中的字段數目相同。不在字段清單中的字段被賦予預設值或NULL(當未定義預設值)。
INSERT的第二種形式從SELECT語句中擷取資料。若未定義字段清單,則從SELECT得到的字段的數目必須與表中的字段數目相同,否則應與定義的字段清單中的字段數目相同。SELECT的每一行結果在表中插入一個新的條目。SELECT可以是簡單的或者複合的。如果SELECT語句帶有 ORDER BY子句,ORDER BY會被忽略。
這裡我們可以這樣做:
sqlite> INSERT INTO "SensorData" VALUES(NULL, 1, 0, '200605011206', 18.9);
sqlite> INSERT INTO "SensorData" VALUES(2, 1, 0, '200605011306', 16.4);
sqlite> INSERT INTO "SensorData" VALUES(3, 1, 0, '200605011406', 15.3);
sqlite> INSERT INTO "SensorData" VALUES(4, 1, 0, '200605011506', 15.5);
sqlite>
很簡單對不對?簡直太easy了。
2.3 線上幫助
前面兩節,我們已經知道了sqlite文法最基本的用法。下面可以看看如何獲得聯機幫助。
很簡單,輸入 .help 就行了。注意要help前加上“.”,這與上面說的以分号結尾有點不同,因為help指令被視為特殊指令。
sqlite> .help
.databases List names and files of attached databases
.dump ?TABLE? ... Dump the database in an SQL text format
.echo ON|OFF Turn command echo on or off
.exit Exit this program
.explain ON|OFF Turn output mode suitable for EXPLAIN on or off.
.header(s) ON|OFF Turn display of headers on or off
.help Show this message
.import FILE TABLE Import data from FILE into TABLE
.indices TABLE Show names of all indices on TABLE
.mode MODE ?TABLE? Set output mode where MODE is on of:
csv Comma-separated values
column Left-aligned columns. (See .width)
html HTML <table> code
insert SQL insert statements for TABLE
line One value per line
list Values delimited by .separator string
tabs Tab-separated values
tcl TCL list elements
.nullvalue STRING Print STRING in place of NULL values
.output FILENAME Send output to FILENAME
.output stdout Send output to the screen
.prompt MAIN CONTINUE Replace the standard prompts
.quit Exit this program
.read FILENAME Execute SQL in FILENAME
.schema ?TABLE? Show the CREATE statements
.separator STRING Change separator used by output mode and .import
.show Show the current values for various settings
.tables ?PATTERN? List names of tables matching a LIKE pattern
.timeout MS Try opening locked tables for MS milliseconds
.width NUM NUM ... Set column widths for "column" mode
sqlite>
這裡看到的指令都帶有“.”開頭,或者說sqlite下,隻有這些指令是需要帶“.”的。我們會經常用到的指令有:
.output FILENAME
.output stdout
.quit
.read FILENAME
.schema ?TABLE?
.dump ?TABLE? ...
.echo ON|OFF
.exit
在下面會涉及到這些具體内容的。我們慢慢來。
2.4 檢視目前資料庫下的所有表
當資料庫越來越大時,我們也許并不太記得資料庫中有多少個表了,這時就需要檢視目前資料庫下的有些什麼表。
我們可以用 .tables 指令 。
sqlite> .tables
SensorData
sqlite>
2.5 退出sqlite3
對于初學者,也許不知道怎麼安全退出,不過如果是從頭看到此處的讀者也許已經知道了,
因為剛才 .help 指令已經告訴我們答案了。安全退出有兩個指令:.exit 和 .quit
好了,我們已經建立一個名為zieckey.db的資料庫,并在其中建立一個名為 SensorData 的表.
現在我們想退出,那麼可以用到剛剛提到的 .exit 和 .quit 指令。
例如我們可以這樣退出:
sqlite> .exit
這裡需要說明一下,如果不是用 .exit 和 .quit 這兩個指令退出,我們對資料庫的修改有可能丢失。
三、在Linux下用C/C++語言操縱SQLite資料庫
1. 說明
這裡我們假設你已經編譯好了sqlite的庫檔案 :
libsqlite3.a libsqlite3.la libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 pkgconfig
和可執行檔案 : sqlite3
我們再假設你的sqlite3的安裝目錄在 /usr/local/sqlite3 目錄下。
如果不是,我們可以這樣做,将你的安裝檔案複制到 /usr/local/sqlite3 這個目錄,
這樣我們好在下面的操作中更加統一,進而減少出錯的機率
例如:[root@localhost home]# cp -rf sqlite-3.3.8-ix86/ /usr/local/sqlite3
這裡假設 /home/sqlite-3.3.8-ix86/ 是你的安裝目錄,也就是說你的sqlite原來就是安裝在這裡
這樣之後,我們的sqlite3的庫檔案目錄是:/usr/local/sqlite3/lib
可執行檔案 sqlite3 的目錄是: /usr/local/sqlite3/bin
頭檔案 sqlite3.h 的目錄是: /usr/local/sqlite3/include
可以用ls指令檢視下:
[root@localhost sqlite]# ls /usr/local/sqlite3/lib
libsqlite3.a libsqlite3.la libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 pkgconfig
好拉,現在開始我們的Linux下sqlite3程式設計之旅。
2. 開始
這裡我們現在進行一個測試。
現在我們來寫個C/C++程式,調用 sqlite 的 API 接口函數。
下面是一個C程式的例子,顯示怎麼使用 sqlite 的 C/C++ 接口. 資料庫的名字由第一個參數取得且第二個參數或更多的參數是 SQL 執行語句. 這個函數調用sqlite3_open() 在 16 行打開資料庫,并且sqlite3_close() 在 25 行關閉資料庫連接配接。
[root@localhost temp]# vi opendbsqlite.c
按下 i 鍵切換到輸入模式,輸入下列代碼:
// name: opendbsqlite.c
// This prog is used to test C/C++ API for sqlite3.It is very simple,ha!
// Author : zieckey All rights reserved.
// date : 2006/11/13
#include <stdio.h>
#include <sqlite3.h>
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
//打開指定的資料庫檔案,如果不存在将建立一個同名的資料庫檔案
rc = sqlite3_open("zieckey.db", &db);
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
sqlite3_close(db); //關閉資料庫
return 0;
}
退出,儲存。(代碼輸入完成後,按下 Esc 鍵,然後輸入: :wq ,回車就好拉)
好拉,現在編譯:[root@localhost temp]# gcc opendbsqlite.c -o db.out
或者遇到這樣的問題:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
opendbsqlite.c:11:21: sqlite3.h: 沒有那個檔案或目錄
opendbsqlite.c: In function `main':
opendbsqlite.c:19: `sqlite3' undeclared (first use in this function)
opendbsqlite.c:19: (Each undeclared identifier is reported only once
opendbsqlite.c:19: for each function it appears in.)
opendbsqlite.c:19: `db' undeclared (first use in this function)
這是由于沒有找到頭檔案的原因。
也許會碰到類似這樣的問題:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
/tmp/ccTkItnN.o(.text+0x2b): In function `main':
: undefined reference to `sqlite3_open'
/tmp/ccTkItnN.o(.text+0x45): In function `main':
: undefined reference to `sqlite3_errmsg'
/tmp/ccTkItnN.o(.text+0x67): In function `main':
: undefined reference to `sqlite3_close'
/tmp/ccTkItnN.o(.text+0x8f): In function `main':
: undefined reference to `sqlite3_close'
collect2: ld returned 1 exit status
這是個沒有找到庫檔案的問題。
下面我們着手解決這些問題。
由于用到了使用者自己的庫檔案,所用應該指明所用到的庫,我們可以這樣編譯:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3
我用用 -lsqlite3 選項就可以了(前面我們生成的庫檔案是 libsqlite3.so.0.8.6 等,
去掉前面的lib和後面的版本标志,就剩下 sqlite3 了是以是 -lsqlite3 )。
如果我們在編譯安裝的時候,選擇了安裝路徑,例如這樣的話:
.......
# ../sqlite/configure --prefix=/usr/local/sqlite3
# make
.......
這樣編譯安裝時,sqlite的庫檔案将會生成在 /usr/local/sqlite3/lib 目錄下
sqlite的頭檔案将會生成在 /usr/local/sqlite3/include 目錄下
這時編譯還要指定庫檔案路徑,因為系統預設的路徑沒有包含 /usr/local/sqlite3/lib
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib
如果還不行的話,可能還需要指定頭檔案 sqlite3.h 的路徑,如下:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
這樣編譯應該就可以了 ,運作:
[root@localhost temp]# ./db.out
./db.out: error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory
運作是也許會出現類似上面的錯誤。
這個問題因為剛剛編譯的時候沒有選擇靜态編譯,那麼按照預設的編譯就動态編譯的。
動态編譯後,由于可執行檔案在運作時要調用系統庫檔案,
那麼沿着系統預設的庫檔案搜尋路徑搜尋,就可能找不到我們現在所需的庫檔案。
緻使出現 "error while loading shared libraries" 等錯誤。
我們可以這樣解決:
方法一:靜态編譯
在編譯時加上 -static 參數,例如
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include -static
[root@localhost temp]# ll
總用量 1584
-rwxr-xr-x 1 root root 1596988 11月 13 10:50 db.out
-rw-r--r-- 1 root root 614 11月 13 10:31 opendbsqlite.c
可以看到輸出檔案 db.out ,其大小為: 1596988k
運作,好了,沒有出現錯誤
[root@localhost temp]# ./db.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
方法二:重新配置系統環境變量 LD_LIBRARY_PATH
這時需要指定 libsqlite3.so.0 庫檔案的路徑,也就是配置系統環境變量 LD_LIBRARY_PATH ,
使系統能夠找到 libsqlite3.so.0 。
去掉 -static ,再編譯:
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
[root@localhost temp]# ll
總用量 36
-rwxr-xr-x 1 root root 12716 11月 13 10:56 db.out
-rw-r--r-- 1 root root 614 11月 13 10:31 opendbsqlite.c
[root@localhost temp]#
可以看到輸出檔案 db.out ,其大小為: 12716k,比剛才的靜态編譯要小得多。
是以我們推薦使用動态編譯的方法。
好了,現在我們來指定系統環境變量 LD_LIBRARY_PATH 的值
在shell下輸入:
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
看看現在系統環境設定:
[root@localhost temp]#env
SSH_AGENT_PID=3511
HOSTNAME=localhost.localdomain
DESKTOP_STARTUP_ID=
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=29388238
OLDPWD=/mnt/usb/wuruan/sqlite
QTDIR=/usr/lib/qt-3.1
USER=root
LD_LIBRARY_PATH=/usr/local/sqlite3/lib:
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
SSH_AUTH_SOCK=/tmp/ssh-XXt14q3a/agent.3456
SESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/3456
USERNAME=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
INPUTRC=/etc/inputrc
PWD=/mnt/usb/wuruan
XMODIFIERS=@im=fcitx
LANG=zh_CN.GB18030
GDMSESSION=Default
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/root
SHLVL=2
LANGUAGE=zh_CN.GB18030:zh_CN.GB2312:zh_CN
GNOME_DESKTOP_SESSION_ID=Default
BASH_ENV=/root/.bashrc
LOGNAME=root
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0.0
G_BROKEN_FILENAMES=1
COLORTERM=gnome-terminal
XAUTHORITY=/root/.Xauthority
_=/bin/env
看到了吧,LD_LIBRARY_PATH這一行開始就是sqlite3的庫檔案路徑:
LD_LIBRARY_PATH=/usr/local/sqlite3/lib: ............
好拉,現在再運作
[root@localhost temp]# ./db.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
是不是很有成就感阿 ,呵呵,這個上手還是很快的。
3. 插入:insert
剛剛我們知道了怎麼調用 sqlite3 的C/C++的API函數接口,下面我們看看怎麼在C語言中向資料庫插入資料。
好的,我們現編輯一段c代碼,取名為 insert.c
// name: insert.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打開指定的資料庫檔案,如果不存在将建立一個同名的資料庫檔案
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
//建立一個表,如果該表存在,則不建立,并給出提示資訊,存儲在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("%s\n",zErrMsg);
#endif
//插入資料
sql = "INSERT INTO \"SensorData\" VALUES( NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES( NULL , 1 , 1 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sqlite3_close(db); //關閉資料庫
return 0;
}
好的,将上述代碼寫入一個檔案,并将其命名為 insert.c 。
解釋:
sqlite3_exec的函數原型說明如下:
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be executed */
sqlite_callback, /* Callback function */
void *, /* 1st argument to callback function */
char **errmsg /* Error msg written here */
);
編譯:
[root@localhost temp]# gcc insert.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
insert.c:28:21: warning: multi-line string literals are deprecated
[root@localhost temp]#
執行
[root@localhost temp]# ./a.out
./a.out: error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory
[root@localhost temp]#
同樣的情況,如上文處理方法:
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
(null)
(null)
(null)
[root@localhost temp]#
運作成功了,好了,現在我們來看看是否插入了資料
[root@localhost temp]# /usr/local/sqlite3/bin/sqlite3 zieckey.db
SQLite version 3.3.8
Enter ".help" for instructions
sqlite> select * from SensorData;
1|1|1|200605011206|18.9
2|1|1|200605011306|16.4
sqlite>
哈哈,已經插入進去了,不是嗎?
很簡單是不?
4. 查詢: SELETE
好了,我們知道了怎麼調用 sqlite3 的C/C++的API函數接口去建立資料庫、建立表格、并插入資料,
下面我們看看怎麼在C語言中查詢資料庫中的資料。
好的,我們現編輯一段c代碼,取名為 query.c
// name: query.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打開指定的資料庫檔案,如果不存在将建立一個同名的資料庫檔案
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
//建立一個表,如果該表存在,則不建立,并給出提示資訊,存儲在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
//插入資料
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
int nrow = 0, ncolumn = 0;
char **azResult; //二維數組存放結果
//查詢資料
/*
int sqlite3_get_table(sqlite3*, const char *sql,char***result , int *nrow , int *ncolumn ,char **errmsg );
result中是以數組的形式存放你所查詢的資料,首先是表名,再是資料。
nrow ,ncolumn分别為查詢語句傳回的結果集的行數,列數,沒有查到結果時傳回0
*/
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \n" , nrow , ncolumn );
printf( "\nThe result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//釋放掉 azResult 的記憶體空間
sqlite3_free_table( azResult );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sqlite3_close(db); //關閉資料庫
return 0;
}
我們這裡用到了一個查詢的語句是 "SELECT * FROM SensorData " ,
在C語言中對應的函數接口是 sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
這個函數接口的解釋在程式中已經注釋。
下面我們編譯運作下看看,
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# gcc query.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
query.c:29:21: warning: multi-line string literals are deprecated
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row=2 column=5
The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 1
azResult[12] = 1
azResult[13] = 200605011306
azResult[14] = 16.4
zErrMsg = (null)
這裡我們可以看到,azResult 的前面 5 個資料正好是我們的表 SensorData 的列屬性,
之後才是我們要查詢的資料。是以我們的程式中才有 i<( nrow + 1 ) * ncolumn 的判斷條件:
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
輸出中有 zErrMsg = (null) 這樣的字句,這是 zErrMsg 保留的錯誤資訊,
正如你所看到的,zErrMsg 為空,表明在執行過程中沒有錯誤資訊。
5. 删除:delete
下面我們看看怎麼在C語言中删除資料庫中的特定的資料。
好的,我們現編輯一段c代碼,取名為 delete.c
// name: delete.c
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey All rights reserved.
// date : 2006/11/18
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#define _DEBUG_
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); //打開指定的資料庫檔案,如果不存在将建立一個同名的資料庫檔案
if( rc )
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
else printf("You have opened a sqlite3 database named zieckey.db successfully!\nCongratulations! Have fun ! ^-^ \n");
//建立一個表,如果該表存在,則不建立,并給出提示資訊,存儲在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(
ID INTEGER PRIMARY KEY,
SensorID INTEGER,
SiteNum INTEGER,
Time VARCHAR(12),
SensorParameter REAL
);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
//插入資料
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 23 , 45 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"SensorData\" VALUES(NULL , 34 , 45 , '200605011306', 15.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
int nrow = 0, ncolumn = 0;
char **azResult; //二維數組存放結果
//查詢資料
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \n" , nrow , ncolumn );
printf( "\nThe result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//删除資料
sql = "DELETE FROM SensorData WHERE SensorID = 1 ;" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( "\n\n\n\nrow:%d column=%d " , nrow , ncolumn );
printf( "\nAfter deleting , the result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//釋放掉 azResult 的記憶體空間
sqlite3_free_table( azResult );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sqlite3_close(db); //關閉資料庫
return 0;
}
下面我們編譯運作看看,效果如何
[root@localhost temp]# export LD_LIBRARY_PATH=/usr/local/sqlite3/lib:$LD_LIBRARY_PATH
[root@localhost temp]# gcc delete.c -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
delete.c:29:21: warning: multi-line string literals are deprecated
[root@localhost temp]# ./a.out
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row=3 column=5
The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 23
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 16.4
azResult[15] = 3
azResult[16] = 34
azResult[17] = 45
azResult[18] = 200605011306
azResult[19] = 15.4
zErrMsg = (null)
row:2 column=5
After deleting , the result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 2
azResult[6] = 23
azResult[7] = 45
azResult[8] = 200605011306
azResult[9] = 16.4
azResult[10] = 3
azResult[11] = 34
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 15.4
zErrMsg = (null)
從程式輸出結果就可以看出,在删除資料前,我們有三條記錄,
删除資料後我們發現,資料庫内記錄少了。進而實作了我們的删除資料目的。