2007年7月19日 星期四

Cross-Compile sqlite 3.4.0

下載sqlite-3.4.0.tar.gz
$export PATH=/tools/arm-linux-gnueabi/bin/$:PATH
$cd /home/working
$mkdir sqlite-arm-linux
$tar zxvf sqlite-3.4.0.tar.gz
$cd sqlite-arm-linux
$../sqlite-3.4.0/configure --disable-tcl --prefix=/home/working/sqlite-arm-linux/
--host=arm-linux CC=/tools/arm-linux-gnueabi/bin/arm-linux-gcc
$make
$ls .lib

copy libsqlite* 到target board上
如果需要用到執行檔sqlite3
可用
$/tools/arm-linux-gnueabi/bin/arm-linux-strip sqlite3
來decrease file size

2007年7月18日 星期三

[轉]SQLite 用法( 五)--如何用sqlite 執行標準 sql 語法

[本文轉載來源為:http://webmaster.blog.sohu.com/54167184.html]

(2) SQL語句操作
本節介紹如何用sqlite 執行標準 sql 語法。



i.1 執行sql語句

int sqlite3_exec(sqlite3*, const char *sql, sqlite3_callback, void *, char **errmsg );

這就是執行一條 sql 語句的函數。

第1個參數不再說了,是前面open函數得到的指標。說了是關鍵數據架構。

第2個參數const char *sql 是一條 sql 語句,以\0結尾。

第3個參數sqlite3_callback 是回調,當這條語句執行之後,sqlite3會去調用你提供的這個函數。(什麼是回調函數,自己找別的資料學習)

第4個參數void * 是你所提供的指標,你可以傳遞任何一個指標參數到這裡,這個參數最終會傳到回調函數裡面,如果不需要傳遞指標給回調函數,可以填NULL。等下我們再看回調函數的寫法,以及這個參數的使用。

第5個參數char ** errmsg 是錯誤訊息。注意是指標的指標。sqlite3裡面有很多固定的錯誤訊息。執行 sqlite3_exec 之後,執行失敗時可以查閱這個指標(直接 printf(“%s\n”,errmsg))得到一串字元串訊息,這串訊息告訴你錯在什麼地方。sqlite3_exec函數透過修改你傳入的指標的指標,把你提供的指標指向錯誤提示訊息,這樣sqlite3_exec函數外面就可以透過這個 char*得到具體錯誤提示。

說明︰通常,sqlite3_callback 和它後面的 void * 這兩個位置都可以填 NULL。填NULL表示你不需要回調。比如你做 insert 操作,做 delete 操作,就沒有必要使用回調。而當你做 select 時,就要使用回調,因為 sqlite3 把數據查出來,得透過回調告訴你查出了什麼數據。



i.2 exec 的回調

typedef int (*sqlite3_callback)(void*,int,char**, char**);

你的回調函數必須定義成上面這個函數的類型。下面給個簡單的例子︰

//sqlite3的回調函數

// sqlite 每查到一條記錄,就調用一次這個回調

int LoadMyInfo( void * para, int n_column, char ** column_value, char ** column_name )

{

//para是你在 sqlite3_exec 裡傳入的 void * 參數

//透過para參數,你可以傳入一些特殊的指標(比如類指標、架構指標),然後在這裡面強製轉換成對應的類型(這裡面是void*類型,必須強製轉換成你的類型才可用)。然後操作這些數據

//n_column是這一條記錄有多少個字段 (即這條記錄有多少列)

// char ** column_value 是個關鍵值,查出來的數據都儲存在這裡,它實際上是個1維數組(不要以為是2維數組),每一個元素都是一個 char * 值,是一個字段內容(用字元串來表示,以\0結尾)

//char ** column_name 跟 column_value是對應的,表示這個字段的字段名稱



//這裡,我不使用 para 參數。忽略它的存在.



int i;

printf( “記錄包含 %d 個字段\n”, n_column );

for( i = 0 ; i <> 字段值:%s\n”, column_name[i], column_value[i] );

}

printf( “------------------\n“ );

return 0;

}



int main( int , char ** )

{

sqlite3 * db;

int result;

char * errmsg = NULL;



result = sqlite3_open( “c:\\Dcg_database.db”, db );

if( result != SQLITE_OK )

{

//數據庫打開失敗

return -1;

}

//數據庫操作代碼

//創建一個測試表,表名叫 MyTable_1,有2個字段︰ ID 和 name。其中ID是一個自動增加的類型,以後insert時可以不去指定這個字段,它會自己從0開始增加

result = sqlite3_exec( db, “create table MyTable_1( ID integer primary key autoincrement, name nvarchar(32) )”, NULL, NULL, errmsg );

if(result != SQLITE_OK )

{

printf( “創建表失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

//插入一些記錄

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘走路’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘騎單車’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘坐汽車’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}





//開始查詢數據庫

result = sqlite3_exec( db, “select * from MyTable_1”, LoadMyInfo, NULL, errmsg );



//關閉數據庫

sqlite3_close( db );

return 0;

}



透過上面的例子,應該可以知道如何打開一個數據庫,如何做數據庫基本操作。

有這些知識,基本上可以應付很多數據庫操作了。



i.3 不使用回調查詢數據庫

上面介紹的 sqlite3_exec 是使用回調來執行 select 操作。還有一個方法可以直接查詢而不需要回調。但是,我個人感覺還是回調好,因為代碼可以更加整齊,只不過用回調很麻煩,你得聲明一個函數,如果這個函數是類成員函數,你還不得不把它聲明成 static 的(要問為什麼?這又是C++基礎了。C++成員函數實際上隱藏了一個參數︰this,C++調用類的成員函數的時候,隱含把類指標當成函數的第一個參數傳遞進去。結果,這造成跟前面說的 sqlite 回調函數的參數不相符。只有當把成員函數聲明成 static 時,它才沒有多餘的隱含的this參數)。

雖然回調顯得代碼整齊,但有時候你還是想要非回調的 select 查詢。這可以透過 sqlite3_get_table 函數做到。

int sqlite3_get_table(sqlite3*, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg );

第1個參數不再多說,看前面的例子。

第2個參數是 sql 語句,跟 sqlite3_exec 裡的 sql 是一樣的。是一個很普通的以\0結尾的char *字元串。

第3個參數是查詢結果,它依然一維數組(不要以為是二維數組,更不要以為是三維數組)。它內存佈局是︰第一行是字段名稱,後面是緊接著是每個字段的值。下面用例子來說事。

第4個參數是查詢出多少條記錄(即查出多少行)。

第5個參數是多少個字段(多少列)。

第6個參數是錯誤訊息,跟前面一樣,這裡不多說了。

下面給個簡單例子:

int main( int , char ** )

{

sqlite3 * db;

int result;

char * errmsg = NULL;

char **dbResult; //是 char ** 類型,兩個*號

int nRow, nColumn;

int i , j;

int index;



result = sqlite3_open( “c:\\Dcg_database.db”, db );

if( result != SQLITE_OK )

{

//數據庫打開失敗

return -1;

}

//數據庫操作代碼

//假設前面已經創建了 MyTable_1 表

//開始查詢,傳入的 dbResult 已經是 char **,這裡又加了一個 取位址符,傳遞進去的就成了 char ***

result = sqlite3_get_table( db, “select * from MyTable_1”, dbResult, nRow, nColumn, errmsg );

if( SQLITE_OK == result )

{

//查詢成功



index = nColumn; //前面說過 dbResult 前面第一行數據是字段名稱,從 nColumn 索引開始才是真正的數據

printf( “查到%d條記錄\n”, nRow );

for( i = 0; i < j =" 0"> 字段值:%s\n”, dbResult[j], dbResult [index] );

++index; // dbResult 的字段值是連續的,從第0索引到第 nColumn - 1索引都是字段名稱,從第 nColumn 索引開始,後面都是字段值,它把一個二維的表(道統的行清單示法)用一個扁平的形式來表示

}

printf( “-------\n” );

}

}



//到這裡,不論數據庫查詢是否成功,都釋放 char** 查詢結果,使用 sqlite 提供的功能來釋放

sqlite3_free_table( dbResult );



//關閉數據庫

sqlite3_close( db );

return 0;

}



到這個例子為止,sqlite3 的常用用法都介紹完了。

用以上的方法,再配上 sql 語句,完全可以應付絕大多數數據庫需求。

但有一種情況,用上面方法是無法實現的︰需要insert、select 二進製。當需要處理二進製數據時,上面的方法就沒辦法做到。下面這一節說明如何插入二進製數據

(2) 操作二進製
sqlite 操作二進製數據需要用一個輔助的數據類型︰sqlite3_stmt * 。

這個數據類型記錄了一個“sql語句”。為什麼我把 “sql語句” 用雙引號引起來?因為你可以把 sqlite3_stmt * 所表示的內容看成是 sql語句,但是實際上它不是我們所熟知的sql語句。它是一個已經把sql語句解析了的、用sqlite自己標記記錄的內部數據架構。

正因為這個架構已經被解析了,所以你可以往這個語句裡插入二進製數據。當然,把二進製數據插到 sqlite3_stmt 架構裡可不能直接 memcpy ,也不能像 std::string 那樣用 + 號。必須用 sqlite 提供的函數來插入。



i.1 寫入二進製

下面說寫二進製的步驟。

要插入二進製,前提是這個表的字段的類型是 blob 類型。我假設有這么一張表︰

create table Tbl_2( ID integer, file_content blob )

首先聲明

sqlite3_stmt * stat;

然後,把一個 sql 語句解析到 stat 架構裡去︰

sqlite3_prepare( db, “insert into Tbl_2( ID, file_content) values( 10, ? )”, -1, stat, 0 );

上面的函數完成 sql 語句的解析。第一個參數跟前面一樣,是個 sqlite3 * 類型變量,第二個參數是一個 sql 語句。

這個 sql 語句特別之處在於 values 裡面有個 ? 號。在sqlite3_prepare函數裡,?號表示一個未定的值,它的值等下才插入。

第三個參數我寫的是-1,這個參數含義是前面 sql 語句的長度。如果小於0,sqlite會自動計算它的長度(把sql語句當成以\0結尾的字元串)。

第四個參數是 sqlite3_stmt 的指標的指標。解析以後的sql語句就放在這個架構裡。

第五個參數我也不知道是干什麼的。為0就可以了。

如果這個函數執行成功(返回值是 SQLITE_OK 且 stat 不為NULL ),那麼下面就可以開始插入二進製數據。

sqlite3_bind_blob( stat, 1, pdata, (int)(length_of_data_in_bytes), NULL ); // pdata為數據緩沖區,length_of_data_in_bytes為數據大小,以位元組為單位

這個函數一共有5個參數。

第1個參數︰是前面prepare得到的 sqlite3_stmt * 類型變量。

第2個參數︰?號的索引。前面prepare的sql語句裡有一個?號,假如有多個?號怎么插入?方法就是改變 bind_blob 函數第2個參數。這個參數我寫1,表示這裡插入的值要替換 stat 的第一個?號(這裡的索引從1開始計數,而非從0開始)。如果你有多個?號,就寫多個 bind_blob 語句,並改變它們的第2個參數就替換到不同的?號。如果有?號沒有替換,sqlite為它取值null。

第3個參數︰二進製數據起始指標。

第4個參數︰二進製數據的長度,以位元組為單位。

第5個參數︰是個析夠回調函數,告訴sqlite當把數據處理完後調用此函數來析夠你的數據。這個參數我還沒有使用過,因此理解也不深刻。但是一般都填NULL,需要釋放的內存自己用代碼來釋放。

bind完了之後,二進製數據就進入了你的“sql語句”裡了。你現下可以把它儲存到數據庫裡︰

int result = sqlite3_step( stat );

透過這個語句,stat 表示的sql語句就被寫到了數據庫裡。

最後,要把 sqlite3_stmt 架構給釋放︰

sqlite3_finalize( stat ); //把剛才分發的內容析構掉



i.2 讀出二進製

下面說讀二進製的步驟。

跟前面一樣,先聲明 sqlite3_stmt * 類型變量︰

sqlite3_stmt * stat;

然後,把一個 sql 語句解析到 stat 架構裡去︰

sqlite3_prepare( db, “select * from Tbl_2”, -1, stat, 0 );

當 prepare 成功之後(返回值是 SQLITE_OK ),開始查詢數據。

int result = sqlite3_step( stat );

這一句的返回值是 SQLITE_ROW 時表示成功(不是 SQLITE_OK )。

你可以循環執行 sqlite3_step 函數,一次 step 查詢出一條記錄。直到返回值不為 SQLITE_ROW 時表示查詢結束。

然後開始獲取第一個字段︰ID 的值。ID是個整數,用下面這個語句獲取它的值︰

int id = sqlite3_column_int( stat, 0 ); //第2個參數表示獲取第幾個字段內容,從0開始計算,因為我的表的ID字段是第一個字段,因此這裡我填0



下面開始獲取 file_content 的值,因為 file_content 是二進製,因此我需要得到它的指標,還有它的長度︰

const void * pFileContent = sqlite3_column_blob( stat, 1 );

int len = sqlite3_column_bytes( stat, 1 );

這樣就得到了二進製的值。

把 pFileContent 的內容儲存出來之後,不要忘了釋放 sqlite3_stmt 架構︰

sqlite3_finalize( stat ); //把剛才分發的內容析構掉



i.3 重複使用 sqlite3_stmt 架構

如果你需要重複使用 sqlite3_prepare 解析好的 sqlite3_stmt 架構,需要用函數︰ sqlite3_reset。

result = sqlite3_reset(stat);

這樣, stat 架構又成為 sqlite3_prepare 完成時的狀態,你可以重新為它 bind 內容

2007年7月17日 星期二

[轉]SQLite 用法(四)--sqlite3編譯安裝與交叉編譯

[本文轉載來源為:http://blog.chinaunix.net/u/16292/showart_149594.html]
sqlite-3.3.6編譯安裝與交叉編譯
作者: zieckey@yahoo.com.cn
下文介紹的內容都是基於 Linux RedHat 9.0 平台的。
一、PC機編譯安裝
請閱讀在安裝包裡的 INSTALL 文件。或者使用PEAR installer with "pear install sqlite"。SQLite已經內置了,你不需要安裝任何附加的軟件(additional software)。
Windows users可以下載SQLite擴展DLL(php_sqlite.dl)。
這裡簡單介紹一下:
假設你得到的是源代碼sqlite-3.3.6.tar.gz,這裡將告訴你怎麼編譯它。
解壓sqlite-3.3.6.tar.gz 到 /home目錄下
For example:
tar zxvf sqlite-3.3.6.tar.gz -C /home
cd /home
mkdir sqlite-ix86-linux
cd /home/sqlite-ix86-linux/
../sqlite-3.3.6/configure --prefix=/home/sqlite-ix86-linux/
編譯並安裝,然後生成幫助文檔
make && make install && make doc
如果出現下列錯誤
../sqlite-3.3.6/src/tclsqlite.c: In function `DbUpdateHandler':
../sqlite-3.3.6/src/tclsqlite.c:333: warning: passing arg 3 of `Tcl_ListObjAppendElement' makes pointer from integer without a cast
../sqlite-3.3.6/src/tclsqlite.c: In function `tclSqlFunc':
../sqlite-3.3.6/src/tclsqlite.c:419: warning: passing arg 1 of `Tcl_NewByteArrayObj' discards qualifiers from pointer target type
這個都是tcl相關的錯誤,可以先安裝ActiveTcl以解決.假如你不需要tcl支持,那麼這個錯誤可以這樣避免:
cd /home/sqlite-ix86-linux/
../sqlite-3.3.6/configure --disable-tcl --prefix=/home/sqlite-ix86-linux/
編譯並安裝,然後生成幫助文檔
make && make install && make doc
不出意外,將不會出現錯誤,那麼
庫文件已經生成在 /home/sqlite-ix86-linux/lib 目錄下
可執行文件sqlite3已經生成在 /home/sqlite-ix86-linux/bin 目錄下
下面創建一個新的數據庫文件名叫"zieckey.db" (當然你可以使用不同的名字) 來測試數據庫.
直接輸入: /home/sqlite-ix86-linux/bin/sqlite3 test.db
如果出現下面字樣表明編譯安裝已經成功了.
SQLite version 3.3.6
Enter ".help" for instructions
sqlite>

二、交叉編譯sqlite.3.3.6.tar.gz庫文件
tar zxvf sqlite-3.3.6.tar.gz -C /home (這一步前面已經有了,為了完整性,這裡還是寫出來)
mkdir /home/sqlite-arm-linux
設置交叉編譯環境
export PATH=/usr/local/arm-linux/bin:$PATH

cd /home/sqlite-arm-linux/
../sqlite-3.3.6/configure --disable-tcl --prefix=/home/sqlite-arm-linux/ --host=arm-linux
這步出現錯誤而沒有生成Makefile
configure: error: unable to find a compiler for building build tools

前面檢查arm-linux-gcc都通過了,怎麼還說沒有找到編譯器呢?花了點時間看configure的腳本,太複雜了,又結合configure.ac看了一下。原來是要設置config_TARGET_CC和config_BUILD_CC兩個環境變量。config_TARGET_CC是交叉編譯器,config_BUILD_CC是主機編譯器。重來:
export config_BUILD_CC=gcc
export config_TARGET_CC=arm-linux-gcc
../sqlite-3.3.6/configure --disable-tcl --prefix=/home/sqlite-arm-linux/ --host=arm-linux
又出現如下錯誤
checking for /usr/include/readline.h... configure: error: cannot check for file existence when cross compiling
說readline.h的錯,找到readline.h在/usr/include/readline/readline.h目錄,我想這樣解決
ln -s /usr/include/readline/readline.h /usr/include/readline.h
但還是不行
../sqlite-3.3.6/configure --disable-tcl --prefix=/home/sqlite-arm-linux/ --host=arm-linux
還是出現如下同樣的錯誤
checking for /usr/include/readline.h... configure: error: cannot check for file existence when cross compiling

上面說是要檢查交叉編譯環境,我可以肯定我的交叉編譯環境是正確的,
所以我決定欺騙configure,我是這樣做的
cd /home/sqlite-3.3.6
將該目錄下的 configure 文件的部分內容修改下(這裡是根據 test "$cross_compiling" = yes && 找到的 ),
這樣可以讓configure不去檢查你的交叉編譯環境。
20420行 { (exit 1); exit 1; }; }改為 { (echo 1); echo 1; }; }
20446行 { (exit 1); exit 1; }; }改為 { (echo 1); echo 1; }; }
在回去重新配置下:
cd /home/sqlite-arm-linux/
../sqlite-3.3.6/configure --disable-tcl --prefix=/home/sqlite-arm-linux/ --host=arm-linux
中間打印信息出現如下錯誤信息,
checking for /usr/include/readline.h... configure: error: cannot check for file existence when cross compiling
但是還是生成了Makefile文件一個libtool腳本,這些將在make時用到.
注意:
如果Makefile文件中有如下語句
BCC = arm-linux-gcc -g -O2
請將其改掉,改成:
BCC = gcc -g -O2

編譯並安裝
make && make install
這裡如果不出意外,將不會出現錯誤,那麼
庫文件已經生成在 /home/sqlite-ix86-linux/lib 目錄下
好了,就到這裡。

[轉]SQLite 用法(三)--用C操作sqlite3

[本文轉載來源為:http://blog.chinaunix.net/u/16292/showart_215856.html]

如何在Linux下用C/C++語言操作數據庫sqlite3 作者:zieckey(zieckey@yahoo.com.cn)
All Rights Reserved!

0. 引言

我們這篇文章主要講述了如何在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
#include

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);
exit(1);
}
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
#include
#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);
exit(1);
}
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;
11120060501120618.9
21120060501130616.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
#include
#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);
exit(1);
}
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
#include
#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);
exit(1);
}
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)


從程序輸出結果就可以看出,在刪除數據前,我們有三條記錄,
刪除數據後我們發現,數據庫內記錄少了。從而實現了我們的刪除數據目的。


總結:
在這篇文章裡,我們主要講述了如何在C/C++語言中調用 sqlite 的函數接口來實現對數據庫的管理,
包括創建數據庫、創建表格、插入數據、查詢數據、刪除數據等。而這些操作似乎都很簡單不是嗎?



[轉]SQLite 用法(二)--簡單SQL語法使用

[本文轉載來源為:http://openvanilla.org/wiki/zh/index.php?title=SQLite%E4%BD%BF%E7%94%A8%E6%95%99%E5%AD%B8]

SQLite使用教學
OpenVanilla輸入法與文字處理架構
OS X自從10.4後把SQLite這套相當出名的資料庫軟體,放進了作業系統工具集裡。OS X包裝的是第三版的SQLite,又稱SQLite3。這套軟體有幾個特色:

軟體屬於公共財(public domain),SQLite可說是某種「美德軟體」(virtueware),作者本人放棄著作權,而給使用SQLite的人以下的「祝福」(blessing):
May you do good and not evil. 願你行善莫行惡
May you find forgiveness for yourself and forgive others. 願你原諒自己寬恕他人
May you share freely, never taking more than you give. 願你寬心與人分享,所取不多於你所施予
支援大多數的SQL指令(下面會簡單介紹)。
一個檔案就是一個資料庫。不需要安裝資料庫伺服器軟體。
完整的Unicode支援(因此沒有跨語系的問題)。
速度很快。
目前在OS X 10.4裡,SQLite是以/usr/bin/sqlite3的形式包裝,也就說這是一個命令列工具,必須先從終端機(Terminal.app或其他程式)進入shell之後才能使用。網路上有一些協助使用SQLite的視覺化工具,但似乎都沒有像CocoaMySQL(配合MySQL資料庫使用)那般好用。或許隨時有驚喜也未可知,以下僅介紹命令列的操作方式。

SQLite顧名思議是以SQL為基礎的資料庫軟體,SQL是一套強大的資料庫語言,主要概念是由「資料庫」、「資料表」(table)、「查詢指令」(queries)等單元組成的「關聯性資料庫」(進一步的概念可參考網路上各種關於SQL及關聯性資料庫的文件)。因為SQL的查詢功能強大,語法一致而入門容易,因此成為現今主流資料庫的標準語言(微軟、Oracle等大廠的資料庫軟體都提供SQL語法的查詢及操作)。

以下我們就建立資料庫、建立資料表及索引、新增資料、查詢資料、更改資料、移除資料、sqlite3命令列選項等幾個項目做簡單的介紹。


[編輯]建立資料庫檔案
用sqlite3建立資料庫的方法很簡單,只要在shell下鍵入(以下$符號為shell提示號,請勿鍵入):

$ sqlite3 foo.db3
如果目錄下沒有foo.db3,sqlite3就會建立這個資料庫。sqlite3並沒有強制資料庫檔名要怎麼取,因此如果你喜歡,也可以取個例如foo.icannameitwhateverilike的檔名。

[編輯]在sqlite3提示列下操作
進入了sqlite3之後,會看到以下文字:

SQLite version 3.1.3
Enter ".help" for instructions
sqlite>
這時如果使用.help可 以取得求助,.quit則是離開(請注意:不是quit)

[編輯]SQL的指令格式
所有的SQL指令都是以分號(;)結尾的。如果遇到兩個減號(--)則代表註解,sqlite3會略過去。

[編輯]建立資料表
假設我們要建一個名叫film的資料表,只要鍵入以下指令就可以了:

create table film(title, length, year, starring);
這樣我們就建立了一個名叫film的資料表,裡面有name、length、year、starring四個欄位。

這個create table指令的語法為:

create table table_name(field1, field2, field3, ...);
table_name是資料表的名稱,fieldx則是欄位的名字。sqlite3與許多SQL資料庫軟體不同的是,它不在乎欄位屬於哪一種資料型態:sqlite3的欄位可以儲存任何東西:文字、數字、大量文字(blob),它會在適時自動轉換。

[編輯]建立索引
如果資料表有相當多的資料,我們便會建立索引來加快速度。好比說:

create index film_title_index on film(title);
意思是針對film資料表的title欄位,建立一個名叫film_title_index的索引。這個指令的語法為

create index index_name on table_name(field_to_be_indexed);
一旦建立了索引,sqlite3會在針對該欄位作查詢時,自動使用該索引。這一切的操作都是在幕後自動發生的,無須使用者特別指令。

[編輯]加入一筆資料
接下來我們要加入資料了,加入的方法為使用insert into指令,語法為:

insert into table_name values(data1, data2, data3, ...);
例如我們可以加入

insert into film values ('Silence of the Lambs, The', 118, 1991, 'Jodie Foster');
insert into film values ('Contact', 153, 1997, 'Jodie Foster');
insert into film values ('Crouching Tiger, Hidden Dragon', 120, 2000, 'Yun-Fat Chow');
insert into film values ('Hours, The', 114, 2002, 'Nicole Kidman');
如果該欄位沒有資料,我們可以填NULL。


[編輯]查詢資料
講到這裡,我們終於要開始介紹SQL最強大的select指令了。我們首先簡單介紹select的基本句型:

select columns from table_name where expression;
最常見的用法,當然是倒出所有資料庫的內容:

select * from film;
如果資料太多了,我們或許會想限制筆數:

select * from film limit 10;
或是年份比較早的電影先列出來(預設為 asc):

select * from film order by year limit 10;
或是年份比較晚的電影先列出來:

select * from film order by year desc limit 10;
或是我們只想看電影名稱跟年份:

select title, year from film order by year desc limit 10;
查所有茱蒂佛斯特演過的電影:

select * from film where starring='Jodie Foster';
查所有演員名字開頭叫茱蒂的電影('%'、'_' 符號便是 SQL 的萬用字元,前者代表任意長度字元,後者代表任意一個字元):

select * from film where starring like 'Jodie%';
查所有演員名字以茱蒂開頭、年份晚於1985年、年份晚的優先列出、最多十筆,只列出電影名稱和年份:

select title, year from film where starring like 'Jodie%' and year >= 1985 order by year desc limit 10;
有時候我們只想知道資料庫一共有多少筆資料:

select count(*) from film;
有時候我們只想知道1985年以後的電影有幾部:

select count(*) from film where year >= 1985;
(進一步的各種組合,要去看SQL專書,不過你大概已經知道SQL為什麼這麼流行了:這種語言允許你將各種查詢條件組合在一起──而我們還沒提到「跨資料庫的聯合查詢」呢!)

[編輯]如何更改或刪除資料
瞭解select的用法非常重要,因為要在sqlite更改或刪除一筆資料,也是靠同樣的語法。

例如有一筆資料的名字打錯了:

update film set starring='Jodie Foster' where starring='Jodee Foster';
就會把主角欄位裡,被打成'Jodee Foster'的那筆(或多筆)資料,改回成Jodie Foster。

delete from film where year <> output.sql
利用輸出的資料,建立一個一模一樣的資料庫(加上以上指令,就是標準的SQL資料庫備份了):

sqlite3 film.db < title="SQLite%E4%BD%BF%E7%94%A8%E6%95%99%E5%AD%B8">

[轉]SQLite 用法(一)--安裝編譯使用

[本文轉載來源為:http://blog.csdn.net/zieckey/archive/2006/05/04/707507.aspx]
作者: zieckey ( zieckey@yahoo.com.cn )

第一章 從這裡開始
1.0 引言
最近發現網上很多人在文 sqlite 數據庫的問題,可是解答的人並不多。於是萌生了寫點這方面的文章的念頭。雖然我也是剛接觸 sqlite 不到半年,對其瞭解得也不是很深很透徹,但是寫點東西讓初學者能夠很快上手,也算是我的心願之一。也許很多高手會覺得我這是班門弄斧,但是我還是想寫點關於 sqlite 的基本知識,這樣也許能給予某些人一些幫助,希望如此。

下文介紹的內容都是基於 Linux RedHat 9.0 平台的。

1.1 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 ,這裡沒有長長的說明和冗煩的配置。

1.2 下載代碼
取得一份二進制拷貝, 或者是源代碼並自己編譯它。關於這個可以到 http://www.sqlite.org/的下載頁面獲得更多信。
這裡我就不多說了。

1.3 安裝
請閱讀在安裝包裡的 INSTALL 文件。或者使用PEAR installer with "pear install sqlite"。SQLite已經內置了,你不需要安裝任何附加的軟件(additional software)。
Windows users可以下載SQLite擴展DLL(php_sqlite.dl)。
這裡簡單介紹一下:
假設你得到的是源代碼,這裡將告訴你怎麼編譯它。
解壓sqlite-3.0.8.tar.gz 到 /home目錄下
For example:

# tar xzf sqlite.tar.gz –C /home/ ;# Unpack the source tree into "sqlite"
# mkdir sqlite-pc ;# Build will occur in a sibling directory
# cd sqlite-pc ;# Change to the build directory
# ../sqlite/configure ;# Run the configure script
# make ;# Run the makefile.
# make install
生成幫助文檔
# make doc

如果一切順利的話,sqlite的庫文件將會生成在 /usr/local/lib 目錄下。去看看有沒有這些庫文件。
libsqlite3.a libsqlite3.la libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 pkgconfig
好了我們可以進入下一節了。激動人心的時刻到了,我們可以輕而易舉的創建和操縱數據庫了。

1.4 創建一個新數據庫
在 shell 命令行下, 輸入: "sqlite3 zieckey.db"。 將創建一個新的數據庫文件名叫"zieckey.db". (當然你可以使用不同的名字)
輸入 SQL 命令在提示符下創建和寫入新的數據。
例如,新建一個名為zieckey.db的數據庫,並創建一個名為 SensorData 的表,其包含兩個列元素,並插入具體列元素,具體如下
# sqlite3 zieckey.db
SQLite version 3.0.8
Enter ".help" for instructions
sqlite> create table SensorData(one varchar(10), two smallint);
sqlite> insert into SensorData values('hello!',10);
sqlite> insert into SensorData values('goodbye', 20);
sqlite> select * from SensorData;
hello!10
goodbye20
sqlite>
安全退出 sqlite 的方法是
sqlite> .quit
這樣剛才的操作就保存下來了,如果強行退出有可能丟失剛才對數據庫的操作。
是不是相當容易,呵呵,當然拉!如果你會 SQL 語言,你會發現,sqlite的語法幾乎和它一個樣。
這裡先到這裡,後面的章節中我們會繼續學習sqlite的語法規則的。
1.5 寫個C語言程序調用SQLite
現在我們來寫個C/C++程序,調用 sqlite 的 API 接口函數。
下面是一個C程序的例子,顯示怎麼使用 sqlite 的 C/C++ 接口. 這個函數調用sqlite3_open() 在 22 行打開數據庫, sqlite3_exec() 在 27 行執行 SQL 命令, 並且sqlite3_close() 在 31 行關閉數據庫連接。
代碼:

// name: opendbsqlite.c
// This file is used to test C/C++ API for sqlite
// Author : zieckey
// 2006/04/11
#include
#include

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);
exit(1);
}
else printf("open zieckey.db successfully!\n");

sqlite3_close(db); //關閉數據庫
return 0;
}

編譯:# 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

這是個沒有找到庫文件的問題。
由於用到了用戶自己的庫文件,所用應該指明所用到的庫,我們可以這樣編譯:

# gcc opendbsqlite.c -o db.out -lsqlite3

我用用 -lsqlite3 選項就可以了(前面我們生成的庫文件是 libsqlite3.so.0.8.6 等,
去掉前面的lib和後面的版本標誌,就剩下 sqlite3 了所以是 -lsqlite3 )。
如果我們在編譯安裝的時候,選擇了安裝路徑,例如這樣的話:
.......
# ../sqlite/configure --prefix=/usr/local/arm-linux/sqlite-ix86-linux
.......
這樣編譯安裝時,sqlite的庫文件將會生成在 /usr/local/arm-linux/sqlite-ix86-linux/lib 目錄下
這時編譯還要指定庫文件路徑,因為系統默認的路徑沒有包含 /usr/local/arm-linux/sqlite-ix86-linux/lib

# gcc opendbsqlite.c -lsqlite3 -L/usr/local/arm-linux/sqlite-ix86-linux/lib

如果還不行的話,可能還需要指定頭文件 sqlite3.h 的路徑,如下:

# gcc opendbsqlite.c -lsqlite3 -L/usr/local/arm-linux/sqlite-ix86-linux/lib -I/usr/local/arm-linux/sqlite-ix86-linux/include

這樣編譯應該就可以了 ,運行:
# ./db.out
./db.out: error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory
運行是也許會出現類似上面的錯誤。
這個問題是由於運行沿著系統默認路徑沒有找到庫文件引起的。這時需要指定 libsqlite3.so.0 庫文件的路徑。
在shell下輸入:
export LD_LIBRARY_PATH=/usr/local/arm-linux/sqlite-ix86-linux/lib:$LD_LIBRARY_PATH
再運行
# ./db.out
open zieckey.db successfully!
是不是很有成就感阿 ,呵呵,這個上手還是很快的。


總結:這一章裡,我們瞭解了sqlite的基本概貌,並且知道了怎麼創建數據庫,
怎麼向數據庫中插入表格,向表格中插入數據,更令人興奮的是我們知道了
怎麼在C/C++中調用 sqlite 的 API 函數。
寫後感:這是我第一次這樣用心的比較正規的寫關於一個專題的文章。
我也是望著篇文章能帶給你幫助。如果是這樣的話,那我的努力就沒有白費,這讓我覺得我還做了點好事的。
本文一定存在很多不妥或者錯誤之處,還勞煩各位不吝賜教指正。在此跟貼,或者發 email :zieckey@yahoo.com.cn ,本人將不勝感激。
作者鄭重申明:本文可以自由轉載,但請不要去掉版權信息,也不要用於商業用途。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=707507

2007年7月9日 星期一

[轉]Linux環境下使用XFS文件系統

[本文轉載來源為:http://www.raidcn.com/article/2007-5-23/2007523164231.html]

XfS檔案系統是SGI開發的進階日誌檔案系統,XFS極具伸縮性,非常健壯。所幸的是SGI將其移植到了Linux系統中。在linux環境下。目前版本可用的最新XFS檔案系統的為1.2版本,可以很好地工作在2.4核心下。
  一、XFS檔案系統簡介
  主要特性包括以下幾點︰
  數據完全性
  採用XFS檔案系統,當意想不到的宕機發生後,首先,由於檔案系統開啟了日誌功能,所以你磁片上的檔案不再會意外宕機而遭到破壞了。不論目前檔案系統上存儲的檔案與數據有多少,檔案系統都可以根據所記錄的日誌在很短的時間內迅速恢復磁片檔案內容。
  傳輸特性
  XFS檔案系統採用優化算法,日誌記錄對整體檔案操作影響非常小。XFS查詢與分發存儲空間非常快。xfs檔案系統能連續提供快速的回應時間。筆者曾經對XFS、JFS、Ext3、ReiserFS檔案系統進行過測試,XFS檔案檔案系統的性能表現相當出眾。
  可擴展性
  XFS 是一個全64-bit的檔案系統,它可以支援上百萬T位元組的存儲空間。對特大檔案及小尺寸檔案的支援都表現出眾,支援特大數量的目錄。最大可支援的檔案大小為263 = 9 x 1018 = 9 exabytes,最大檔案系統尺寸為18 exabytes。
  XFS使用高的表架構(B+樹),保證了檔案系統可以快速搜索與快速空間分發。XFS能夠持續提供高速操作,檔案系統的性能不受目錄中目錄及檔案數量的限制。
  傳輸帶寬
  XFS 能以接近裸設備I/O的性能存儲數據。在單個檔案系統的測試中,其吞吐量最高可達7GB每秒,對單個檔案的讀寫操作,其吞吐量可達4GB每秒。
二、XFS檔案系統的使用

  1.下載與編譯內核
  下載相應版本的內核補丁,解壓補丁套裝軟件,對系統核心打補丁
  下載位址︰
  對核心打補丁,下載解壓後,得到一個檔案︰xfs-1.1-2.4.18-all.patch檔案。
對核心進行修補如下︰
  # cd /usr/src/linux
  # patch -p1 < /path/to/xfs-1.1-2.4.18-all.patch   修補工作完成後,下一步要進行的工作是編譯核心,將XFS編譯進Linux核心可中。 首先營運以下命令,選擇核心支援XFS檔案系統︰   #make menuconfig   在“檔案系統“選單中選擇︰   <*> SGI XFS filesystem support ##說明︰將XFS檔案系統的支援編譯進核心
  或
   SGI XFS filesystem support ##說明︰以動態加載模塊的模式支援XFS檔案系統
  另外還有兩個選擇︰
  Enable XFS DMAPI ##說明︰對磁片管理的API,存儲管理應用程式使用
  Enable XFS Quota ##說明︰支援配合Quota對用戶使用磁片空間大小管理
  完成以上工作後,退出並儲存核心選擇配置.
  之後,然後編譯內核,安裝核心:
  #make bzImage
  #make module
  #make module_install
  #make install
  如果你對以上複雜繁瑣的工作沒有耐心或沒有把握,那麼可以直接從SGI的站點上下載已經打好補丁的核心,其版本為2.4.18。它是一個rpm套裝軟件,你只要簡單地安裝即可。SGI提交的核心有兩種,分別供smp及單處理器的機器使用。
  2.創建XFS檔案系統
  完成對核心的編譯後,還應下載與之配套的XFSprogs工具套裝軟件,也即mkfs.xfs工具。不然我們無法完成對分區的格式化:即無法將一個分區格式化成XFS檔案系統的格式。要下載的套裝軟件名稱︰xfsprogs-2.0.3。
將所下載的XFSProgs工具解壓,安裝,mkfs.xfs自動安裝在/sbin目錄下。

  #tar xvf xfsprogs-2.0.3.src.tar.gz
  #cd xfsprogs-2.0.3src
  #./configure
  #make
  #make install
  使用mkfs.xfs格式化磁片為xfs檔案系統,方法如下︰
  # /sbin/mkfs.xfs /dev/sda6 #說明︰將分區格式化為xfs檔案系統,以下為顯示內容︰
  meta-data=/dev/sda6 isize=256 agcount=8, agsize=128017 blks
  data = bsize=4096 blocks=1024135, imaxpct=25
  = sunit=0 swidth=0 blks, unwritten=0
  naming =version 2 bsize=4096
  log =internal log bsize=4096 blocks=1200
  realtime =none extsz=65536 blocks=0, rtextents=0
  格式化磁片時,如果mkfs.xfs提示你分區原本已被格式化為其它檔案系統,可以使用參數 -f 強行格式化︰
  #/sbin/mkfs.xfs -f /dev/sda6
  3.加載XFS檔案系統
  #mount -t xfs /dev/sda6 /xfs ##其中/xfs是主分區/下的一個目錄。
  最後,為了讓系統啟動後就自動加載,應該更改/etc/fstab,這樣系統啟動後就會自動加載xfs分區而不必每次都手工加載。
  要說明的一點是目前的xfs由於受linux內存頁限制,在x86版本中,只能實現檔案系統的塊尺寸為4K。另外,XFS檔案系統可以不同的模式mount,即允許檔案系統以讀模式加載,也允許以讀寫模式加載。這是因為xfs檔案系統用作根檔案系統時,為了安全要以只讀模式加載。
  三、檔案系統的遷移
  要使得系統中的其它分區使用XFS檔案系統,還有一步是遷移檔案系統。建議在遷移檔案系統時,首先將磁片上的數據、檔案先備份,以免發生不可挽回的損失,在進行檔案系統轉換之間,最好能將整個系統進行完全備份。這一步有很多種方法,本文僅就筆者的遷移方法加以描述。各位可以按照自己習慣的模式去完成
  如果你想得到一個純的xfs系統(系統的所有檔案系統均採用XFS檔案系統)話,還得將根檔案系統也格式化為xfs檔案系統。這實際上是比較繁雜的一步。因為根檔案系統不能被umount,所以,必須首先創建一個分區,其檔案系統為ext2檔案系統,然後將目前的根分區上的所有檔案與目錄,原原本本地複製到這一個分區,然後更改/etc/fstab檔案,替換原來的根分區。
  方法如下︰
  $ mkfs -t ext2 /dev/hda4
  $ mkdir /mnt/temp
  $ mount -t ext2 /dev/hda4 /mnt/temp
  $ cd /
  $ tar lcvf - .|(cd /mnt/temp; tar xpvf - ) 
以上操作是將根分區上的所有檔案打包,複製到新建立的分區。當然,你也可以直接使用以下命令複製檔案。

  # cp dpR / /mnt/temp
  接著,將下次啟動的根分區更改到/dev/hda4分區,更改/etc/fstab檔案及/etc/lilo.conf ,然後,營運 lilo.
  重新啟動後,新的根分區就已經為/dev/hda4。
  接下來,創建一個xfs檔案系統的分區︰
  $ mkfs -t xfs /dev/hda2
  加載此分區,採用兩樣的方法,將根分區的內容複製到此分區
  $ mount -t xfs /dev/hda2 /mnt/temp
  在根分區下,營運
  $ cd /
  $ tar lcvf - .|(cd /mnt/temp; tar xpvf - )
  再次更改/etc/fstab、/etc/lilo.conf,用新建的xfs分區替換原來的ext2主分區。如下所示︰
  /dev/hda2 / xfs defaults 1 1
  將新建的xfs分區用作根分區,儲存以上設定。再次檢查配置檔案內容,確認無誤後再重新啟動系統。如果你的設定全部正確,那麼系統成功啟動後,你就擁有一個純XFS檔案系統的系統了。