sqlite相關使用

1、SQLite簡介  html

  SQLite是一款輕型的數據庫,是遵照ACID的關聯式數據庫管理系統,它的設計目標是嵌入式的,並且目前已經在不少嵌入式產品中使用了它,它佔用資源很是的低,在嵌入式設備中,可能只須要幾百K的內存就夠了。它可以支持Windows/Linux/Unix等等主流的操做系統,同時可以跟不少程序語言相結合,好比Tcl、PHP、Java等,還有ODBC接口,一樣比起Mysql、PostgreSQL這兩款開源世界著名的數據庫管理系統來說,它的處理速度比他們都快。mysql

  SQLite雖然很小巧,可是支持的SQL語句不會遜色於其餘開源數據庫,它支持的SQL包括:linux

  ATTACH DATABASEgit

  BEGIN TRANSACTION程序員

  commentsql

  COMMIT TRANSACTION數據庫

  COPYexpress

  CREATE INDEX編程

  CREATE TABLEwindows

  CREATE TRIGGER

  CREATE VIEW

  DELETE

  DETACH DATABASE

  DROP INDEX

  DROP TABLE

  DROP TRIGGER

  DROP VIEW

  END TRANSACTION

  EXPLAIN

  expression

  INSERT

  ON CONFLICT clause

  PRAGMA

  REPLACE

  ROLLBACK TRANSACTION

  SELECT

  UPDATE

  同時它還支持事務處理功能等等。也有人說它象Microsoft的Access,有時候真的以爲有點象,可是事實上它們區別很大。好比SQLite 支持跨平臺,操做簡單,可以使用不少語言直接建立數據庫,而不象Access同樣須要Office的支持。若是你是個很小型的應用,或者你想作嵌入式開發,沒有合適的數據庫系統,那麼如今你能夠考慮使用SQLite。目前它的最新版本是 3.2.2,它的官方網站是:http://www.sqlite.org或者http://www.sqlite.com.cn,能在上面得到源代碼和文檔。同時由於數據庫結構簡單,系統源代碼也不是不少,也適合想研究數據庫系統開發的專業人士

  下面是訪問SQLite官方網站: http://www.sqlite.org/ 時第一眼看到關於SQLite的特性.

  1. ACID事務

  2. 零配置 – 無需安裝和管理配置

  3. 儲存在單一磁盤文件中的一個完整的數據庫

  4. 數據庫文件能夠在不一樣字節順序的機器間自由的共享

  5. 支持數據庫大小至2TB

  6. 足夠小, 大體3萬行C代碼, 250K

  7. 比一些流行的數據庫在大部分普通數據庫操做要快

  8. 簡單, 輕鬆的API

  9. 包含TCL綁定, 同時經過Wrapper支持其餘語言的綁定

  10. 良好註釋的源代碼, 而且有着90%以上的測試覆蓋率

  11. 獨立: 沒有額外依賴

  12. Source徹底的Open, 你能夠用於任何用途, 包括出售它

  13. 支持多種開發語言,C, PHP, Perl, Java, ASP.NET,Python

  二、SQLite類型

  SQLite的數據類型

  首先你會接觸到一個讓你驚訝的名詞: Typelessness(無類型). 對! SQLite是無類型的. 這意味着你能夠保存任何類型的數據到你所想要保存的任何表的任何列中, 不管這列聲明的數據類型是什麼(只有在一種狀況下不是, 稍後解釋). 對於SQLite來講對字段不指定類型是徹底有效的. 如:

  Create Table ex1(a, b, c);

  誠然SQLite容許忽略數據類型, 可是仍然建議在你的Create Table語句中指定數據類型. 由於數據類型對於你和其餘的程序員交流, 或者你準備換掉你的數據庫引擎. SQLite支持常見的數據類型, 如:

  CREATE TABLE ex2(

  a VARCHAR(10),

  b NVARCHAR(15),

  c TEXT,

  d INTEGER,

  e FLOAT,

  f BOOLEAN,

  g CLOB,

  h BLOB,

  i TIMESTAMP,

  j NUMERIC(10,5)

  k VARYING CHARACTER (24),

  l NATIONAL VARYING CHARACTER(16)

  );

  前面提到在某種狀況下, SQLite的字段並非無類型的. 即在字段類型爲」Integer Primary Key」時.

 

 

、SQLite的簡單使用

SQLite能夠到官方站點下載http://www.sqlite.org/download.html
包括:Linux,Mac OS X, Windows下的已編譯文件以及源代碼、幫助文檔。windows版的下載地址是:http://www.sqlite.org/sqlite-3_6_23_1.zip,下載後解壓就能夠了。這個文件是工做在命令行下的。雙擊它,就直接進入命令行了。

打開以後是這樣顯示的:

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite>

 

1、建立數據庫

按理說第一步是建立一個數據庫,我是學電子的,對計算機不瞭解,因此我不知道mysql是如何存儲數據庫的。但sqlite將一個數據庫存儲爲一個文件。咱們先進下cmd,關掉原來的sqlite3。

在命令提示符下:

sqlite3 newsql.db

而後就會自動跳到sqlite>命令提示符下。我記得在linux下用時候會在當前目錄下出現newsql.db文件。但在我所用版本的windows下沒有出現。而後我作了些嘗試獲得以下結果:

sqlite3 newsql.db

.quit

注意:.quit是在sqlite提示符下輸入的,表明退出。看目錄下仍是沒有出現數據庫文件。

sqlite3 newsql.db

;

.quit

出現了newsql.db文件。冒號加回車,在sqlite中,表明執行一條語句的意思,雖然我只輸入了一個冒號加回車,沒有輸入任何的語句,但結果已經是不一樣。

2、建立一個表

create table mytable(entry1 varchar(10),entry2 int);

不要忘了加冒號。冒號表明一條語句輸入完畢。

mytable是我建立的表名。create 和table都是系統關鍵字。entry1,entry2是兩個表項。

varchar(10) int是類型。根據我讀到的內容,sqlite是不區分類型,可是咱們仍是要在建立表時,給他一個類型,以便於將這些代碼移植到其餘的數據庫裏面時更加的方便。

3、向表中插入一條記錄

insert into mytable values("hello world",10);

插入完了以後才發現是否是超出定義的大小了?我定義的entry1項是varchar(10)型的,說實在的,我不知這個類型確切來說是什麼意思,我猜應該是10個字符的字符串數組吧。若是那樣的話我是必定超出了。但既然sqlite是不區分類型的,我想應該沒有問題吧。因而我急於看看是否是這樣...

4、查詢表中內容

select * from mytable;

執行這條語句,會列出mytable中的全部內容。

結果爲:

sqlite> select * from mytable;

hello world|10

可見仍是都插入進去了。

sqlite> insert into mytable values("goodbye cruel world",20);

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

也就是說,第一個條目的字符串徹底不受限制。

5、sqlite3 newsql.db的規則

咱們如今退出,而後從新打開數據庫:

sqlite> .quit

F:/sqlite>sqlite3 newsql.db

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

可見sqlite3 newsql.db這個命令規則爲:打開名爲newsql.db這個數據庫,若是不存在則建立一個。

6、查詢一個數據庫中全部的表名

sqlite數據庫中有一個系統創建的表,名爲sqlite_master,查詢這個表能夠獲得全部的表。

sqlite> create table my2ndtable(theonlyentry int);

sqlite> insert into my2ndtable values(30);

sqlite> select * from sqlite_master;

table|mytable|mytable|2|CREATE TABLE mytable(entry1 varchar(10),entry2 int)

table|my2ndtable|my2ndtable|3|CREATE TABLE my2ndtable(theonlyentry int)

對於這個表的定義,官方網站的FAQ中給出以下:

CREATE TABLE sqlite_master ( type TEXT, name TEXT, tbl_name TEXT, rootpage INTEGER, sql TEXT );第一個字段類型顯然會一直是table,第二個字段是名稱分別是mytable和my2ndtable,見上面的結果。第三個字段表名,沒弄懂是什麼意,想必是所在的表的名字,可是一個表的名字和所在的表名不是同樣的嗎?第四個字段rootpage,我也不知指什麼,這個系統的學過數據庫的人應該能知道,有路過的還望告之。第五個字段是建立表的使用的sql語句吧。

7、sqlite的輸出模式

 默認的輸出格式是「列表」。在列表模式下,每條查詢結果記錄被寫在一行中而且每列之間以一個字符串分割符隔開。默認的分隔符是一個管道符號(「|」)。列表符號在當你輸出查詢結果到另一個符號處理的程序(如AWK)中去是尤其有用。

sqlite> .mode list

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

sqlite>

這是正常的模式。

sqlite> .mode csv

sqlite> select * from mytable;

"hello world",10

"goodbye cruel world",20

變化是什麼?字符串被加上了引號。

sqlite> .mode column

sqlite> select * from mytable;

hello world  10

goodbye cru  20

哎呀,第二個字符串被截斷了。

.mode MODE ?TABLE?__  Set output mode where MODE is one 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

這些來自.help命令的輸出結果。

sqlite> .mode html

sqlite> select * from mytable;

<TR><TD>hello world</TD>

<TD>10</TD>

</TR>

<TR><TD>goodbye cruel world</TD>

<TD>20</TD>

</TR>

.mode html是一種較新的輸出方法。

另外,咱們也能夠把輸出結果輸出到文件:

sqlite> .output output.txt

sqlite> select * from mytable;

sqlite> .exit



F:/sqlite>type output.txt

hello world|10

goodbye cruel world|20

8、查看數據庫中全部的表

sqlite> .tables

my2ndtable  mytable

9、查看全部的表的建立語句

sqlite> .schema

CREATE TABLE my2ndtable(theonlyentry int);

CREATE TABLE mytable(entry1 varchar(10),entry2 int);

sqlite> .schema mytable

CREATE TABLE mytable(entry1 varchar(10),entry2 int);

10、數據庫導出和導入

咱們能夠利用這個功能作一個簡單的備份,或是說建立一個一樣的數據庫。

第一步,把數據庫倒出來:

cmd命令提示符下:

F:/sqlite>sqlite3 newsql.db ".dump" >a.sql

此語句將數據庫導出成a.sql數據庫語句文件,執行這個文件就能夠建立一個如出一轍數據庫:

F:/sqlite>sqlite3 copied.db

SQLite version 3.6.23.1

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> select * from mytable;

hello world|10

goodbye cruel world|20

十一、刪除記錄
delete from mytable where entry2=10;
能夠刪掉mytable中全部entry2項爲10的條目。
注意:不是delete * from mytable,而delete from mytable.沒有*.

 

3、SQLite3 C/C++ 開發接口簡介(API函數)

SQLite3SQLite一個全新的版本,它雖然是在SQLite 2.8.13的代碼基礎之上開發的,可是使用了和以前的版本不兼容的數據庫格式和API. SQLite3是爲了知足如下的需求而開發的:

  • 支持UTF-16編碼.
  • 用戶自定義的文本排序方法.
  • 能夠對BLOBs字段創建索引.

所以爲了支持這些特性我改變了數據庫的格式,創建了一個與以前版本不兼容的3.0至於其餘的兼容性的改變,例如全新的API等等,都將在理論介紹以後向你說明,這樣可使你最快的一次性擺脫兼容性問題.

3.0版的和2.X版的API很是類似,可是有一些重要的改變須要注意全部API接口函數和數據結構的前綴都由"sqlite_"改成了"sqlite3_". 這是爲了不同時使用SQLite 2.XSQLite 3.0這兩個版本的時候發生連接衝突.

因爲對於C語言應該用什麼數據類型來存放UTF-16編碼的字符串並無一致的規範所以SQLite使用了普通的void* 類型來指向UTF-16編碼的字符串客戶端使用過程當中能夠把void*映射成適合他們的系統的任何數據類型.

SQLite 3.0一共有83API函數,此外還有一些數據結構和預約義(#defines). (完整的API介紹請參看另外一份文檔.) 不過大家能夠放心,這些接口使用起來不會像它的數量所暗示的那麼複雜最簡單的程序仍然使用三個函數就能夠完成: sqlite3_open(), sqlite3_exec(),  sqlite3_close(). 要是想更好的控制數據庫引擎的執行,可使用提供的sqlite3_prepare()函數把SQL語句編譯成字節碼,而後在使用sqlite3_step()函數來執行編譯後的字節碼sqlite3_column_開頭的一組API函數用來獲取查詢結果集中的信息許多接口函數都是成對出現的,同時有UTF-8UTF-16兩個版本而且提供了一組函數用來執行用戶自定義的SQL函數和文本排序函數.

2.1 如何打開關閉數據庫

   typedef struct sqlite3 sqlite3;
   int sqlite3_open(const char*, sqlite3**);
   int sqlite3_open16(const void*, sqlite3**);
   int sqlite3_close(sqlite3*);
   const char *sqlite3_errmsg(sqlite3*);
   const void *sqlite3_errmsg16(sqlite3*);
   int sqlite3_errcode(sqlite3*);

sqlite3_open() 函數返回一個整數錯誤代碼,而不是像第二版中同樣返回一個指向sqlite3結構體的指針. sqlite3_open()  sqlite3_open16() 的不一樣之處在於sqlite3_open16() 使用UTF-16編碼(使用本地主機字節順序)傳遞數據庫文件名若是要建立新數據庫, sqlite3_open16() 將內部文本轉換爲UTF-16編碼反之sqlite3_open() 將文本轉換爲UTF-8編碼.

打開或者建立數據庫的命令會被緩存,直到這個數據庫真正被調用的時候纔會被執行並且容許使用PRAGMA聲明來設置如本地文本編碼或默認內存頁面大小等選項和參數.

sqlite3_errcode() 一般用來獲取最近調用的API接口返回的錯誤代碼. sqlite3_errmsg() 則用來獲得這些錯誤代碼所對應的文字說明這些錯誤信息將以 UTF-8 的編碼返回,而且在下一次調用任何SQLite API函數的時候被清除. sqlite3_errmsg16()  sqlite3_errmsg() 大致上相同,除了返回的錯誤信息將以 UTF-16 本機字節順序編碼.

SQLite3的錯誤代碼相比SQLite2沒有任何的改變,它們分別是:

#define SQLITE_OK           0   /* Successful result */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

2.2 執行 SQL 語句

       typedef int (*sqlite_callback)(void*,int,char**, char**);
       int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);

sqlite3_exec 函數依然像它在SQLite2中同樣承擔着不少的工做. 該函數的第二個參數中能夠編譯和執行零個或多個SQL語句. 查詢的結果返回給回調函數. 更多地信息能夠查看API 參考.

在SQLite3裏,sqlite3_exec通常是被準備SQL語句接口封裝起來使用的.

       typedef struct sqlite3_stmt sqlite3_stmt;
       int sqlite3_prepare(sqlite3*, const char*, int, sqlite3_stmt**, const char**);
       int sqlite3_prepare16(sqlite3*, const void*, int, sqlite3_stmt**, const void**);
       int sqlite3_finalize(sqlite3_stmt*);
       int sqlite3_reset(sqlite3_stmt*);

sqlite3_prepare 接口把一條SQL語句編譯成字節碼留給後面的執行函數. 使用該接口訪問數據庫是當前比較好的的一種方法.

sqlite3_prepare() 處理的SQL語句應該是UTF-8編碼的. 而sqlite3_prepare16() 則要求是UTF-16編碼的. 輸入的參數中只有第一個SQL語句會被編譯. 第四個參數則用來指向輸入參數中下一個須要編譯的SQL語句存放的SQLite statement對象的指針, 任什麼時候候若是調用 sqlite3_finalize() 將銷燬一個準備好的SQL聲明. 在數據庫關閉以前,全部準備好的聲明都必須被釋放銷燬. sqlite3_reset() 函數用來重置一個SQL聲明的狀態,使得它能夠被再次執行.

SQL聲明能夠包含一些型如"?" 或 "?nnn" 或 ":aaa"的標記,其中"nnn" 是一個整數,"aaa" 是一個字符串. 這些標記表明一些不肯定的字符值(或者說是通配符),能夠在後面用sqlite3_bind 接口來填充這些值. 每個通配符都被分配了一個編號(由它在SQL聲明中的位置決定,從1開始),此外也能夠用 "nnn" 來表示 "?nnn" 這種狀況. 容許相同的通配符在同一個SQL聲明中出現屢次, 在這種狀況下全部相同的通配符都會被替換成相同的值.沒有被綁定的通配符將自動取NULL值.

       int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
       int sqlite3_bind_double(sqlite3_stmt*, int, double);
       int sqlite3_bind_int(sqlite3_stmt*, int, int);
       int sqlite3_bind_int64(sqlite3_stmt*, int, long long int);
       int sqlite3_bind_null(sqlite3_stmt*, int);
       int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
       int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
       int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);

以上是 sqlite3_bind 所包含的所有接口,它們是用來給SQL聲明中的通配符賦值的. 沒有綁定的通配符則被認爲是空值. 綁定上的值不會被sqlite3_reset()函數重置. 可是在調用了sqlite3_reset()以後全部的通配符均可以被從新賦值.

在SQL聲明準備好以後(其中綁定的步驟是可選的), 須要調用如下的方法來執行:

       int sqlite3_step(sqlite3_stmt*);

若是SQL返回了一個單行結果集,sqlite3_step() 函數將返回 SQLITE_ROW , 若是SQL語句執行成功或者正常將返回 SQLITE_DONE , 不然將返回錯誤代碼. 若是不能打開數據庫文件則會返回 SQLITE_BUSY . 若是函數的返回值是 SQLITE_ROW, 那麼下邊的這些方法能夠用來得到記錄集行中的數據:

       const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
       int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
       int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
       int sqlite3_column_count(sqlite3_stmt*);
       const char *sqlite3_column_decltype(sqlite3_stmt *, int iCol);
       const void *sqlite3_column_decltype16(sqlite3_stmt *, int iCol);
       double sqlite3_column_double(sqlite3_stmt*, int iCol);
       int sqlite3_column_int(sqlite3_stmt*, int iCol);
       long long int sqlite3_column_int64(sqlite3_stmt*, int iCol);
       const char *sqlite3_column_name(sqlite3_stmt*, int iCol);
       const void *sqlite3_column_name16(sqlite3_stmt*, int iCol);
       const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
       const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
       int sqlite3_column_type(sqlite3_stmt*, int iCol);

sqlite3_column_count()函數返回結果集中包含的列數. sqlite3_column_count() 能夠在執行了sqlite3_prepare()以後的任什麼時候刻調用. sqlite3_data_count()除了必須要在sqlite3_step()以後調用以外,其餘跟sqlite3_column_count() 大同小異. 若是調用sqlite3_step() 返回值是 SQLITE_DONE 或者一個錯誤代碼, 則此時調用sqlite3_data_count() 將返回 0 ,然而 sqlite3_column_count() 仍然會返回結果集中包含的列數.

返回的記錄集經過使用其它的幾個 sqlite3_column_***() 函數來提取, 全部的這些函數都把列的編號做爲第二個參數. 列編號從左到右以零起始. 請注意它和以前那些從1起始的參數的不一樣.

sqlite3_column_type()函數返回第N列的值的數據類型. 具體的返回值以下:

       #define SQLITE_INTEGER  1
       #define SQLITE_FLOAT    2
       #define SQLITE_TEXT     3
       #define SQLITE_BLOB     4
       #define SQLITE_NULL     5

sqlite3_column_decltype() 則用來返回該列在 CREATE TABLE 語句中聲明的類型. 它能夠用在當返回類型是空字符串的時候. sqlite3_column_name() 返回第N列的字段名. sqlite3_column_bytes() 用來返回 UTF-8 編碼的BLOBs列的字節數或者TEXT字符串的字節數. sqlite3_column_bytes16() 對於BLOBs列返回一樣的結果,可是對於TEXT字符串則按 UTF-16 的編碼來計算字節數. sqlite3_column_blob() 返回 BLOB 數據. sqlite3_column_text() 返回 UTF-8 編碼的 TEXT 數據. sqlite3_column_text16() 返回 UTF-16 編碼的TEXT 數據. sqlite3_column_int() 以本地主機的整數格式返回一個整數值. sqlite3_column_int64() 返回一個64位的整數. 最後, sqlite3_column_double() 返回浮點數.

不必定非要按照sqlite3_column_type()接口返回的數據類型來獲取數據. 數據類型不一樣時軟件將自動轉換.

2.3核心對象和接口

 

SQL數據庫引擎的最主要任務是解析SQL語句。爲了達成這個目的,開發者須要瞭解兩個對象:

 

* 數據庫鏈接對象:sqlite3

* 預處理語句對象:sqlite3_stmt

 

嚴格來說,預處理語句對象並非必須的,由於可以使用sqlite_exec或者sqlite3_get_table這些便於使用的封裝接口,而這些接口封裝並隱藏了預處理語句對象。儘管如此,對預處理對象的理解有助於咱們更充分的使用SQLite。

 

數據庫鏈接對象和預處理對象是由下列的一組C/C++接口調用操縱的:

 

* sqlite3_open()

* sqlite3_prepare()

* sqlite3_step()

* sqlite3_column()

* sqlite3_finalize()

* sqlite3_close()

 

這6個C/C++接口例程和上述的兩個對象構成了SQLite的核心功能。開發者對於它們的理解可以更好的使用SQLite。

 

注意,這個接口例程列表更可能是概念上的意義而不是實際的接口。許多這些接口都出如今各個版本之中。例如,上述列表中的sqlite3_open() 例程實際上有三個不一樣的接口以略微不一樣的方式實現相同的功能:slqite3_open(),sqlite3_open16()和sqlite3_open_v2()。列表中的實際上並不存在sqlite3_column()這個接口。顯示在列表中的 「sqlite3_column()」僅僅是一個佔位,表示一整套用於從表中查詢出各類數據類型的列記錄接口。

 

這裏說明下核心接口的主要功能:

 

* sqlite3_open() 該接口打開與一個SQLite數據庫文件的鏈接並返回一個數據庫鏈接對象。這一般是應用程序調用的第一個SQLite API接口並且也是調用其餘SQLite API接口前須要調用的接口。許多SQLite接口須要一個指向數據庫鏈接對象的指針做爲它們的第一個參數,於是這些接口也能夠理解成是數據庫鏈接對象的操做接口。該接口就是建立了這樣一個數據庫鏈接對象。

 

* sqlite3_prepare() 該接口把一個SQL語句文本轉換成一個預處理語句對象並返回一個指向該對象的指針。這個接口須要一個由先前調用sqlite3_open()返回的數據庫鏈接對象指針以及一個預處理的SQL語句文本字符串爲參數。這個API並不實際解析SQL語句,僅僅是爲後續的解析而對SQL語句進行的預處理。

 

注意新的應用中不建議使用sqlite3_prepare(),而應該使用另外一個接口sqlite3_prepare_v2()。

 

* sqlite3_step() 該接口用於解析一個由先前經過sqlite3_prepare()接口建立的預處理語句,直至返回第一列結果爲止。經過再次調用 sqlite3_step()能夠返回下一列的結果,繼續不斷地調用sqlite3_step()直至整個語句完成爲止。對於那些並不返回結果的語句(例如:INSERT,UPDATE,DELETE語句)一次調用sqlite3_step()就完成了語句的處理。

 

* sqlite3_column() 該接口返回一個由sqlite3_step()解析的預處理語句結果集中當前行的某一列數據。每次執行sqlite3_step()都返回一個新的結果集中的一行。能夠屢次調用sqlite3_column()接口返回那一行中全部列的數據。就像上面所說的那樣,SQLite API中並無sqlite3_column()這樣的接口。取而代之的是一組用於從結果集中查詢出各個列項各類數據類型數據的函數接口。在這組函數接口中,有些接口返回結果集的大小,有些返回結果集的列數。

 

*sqlite3_column_blob()

*sqlite3_column_bytes()

*sqlite3_column_bytes16()

*sqlite3_column_count()

*sqlite3_column_double()

*sqlite3_column_int()

*sqlite3_column_int64()

*sqlite3_column_text()

*sqlite3_column_text16()

*sqlite3_column_type()

*sqlite3_column_value()

 

* sqlite3_finalize() 該接口銷燬以前調用sqlite3_prepare()建立的預處理語句。每個預處理語句都必須調用這個接口進行銷燬以免內存泄

漏。

* sqlite3_close() 該接口關閉一個由以前調用sqlite3_open()建立的數據庫鏈接。全部與該鏈接相關的預處理語句都必須在關閉鏈接以前銷燬。

2.4擴展SQLite

 

SQLite包含一些可用於擴展其功能的一些其餘接口,這些接口包括:

 

 sqlite3_create_collation()

 sqlite3_create_function()

 sqlite3_create_module()

 

sqlite3_create_collation()接口用於爲索引文本建立新的對照序列。sqlite3_create_module()接口用於註冊新的續表實現接口。

 

sqlite3_create_function()接口建立新的SQL函數-便可以是單一的也能夠是組合的接口。新的函數實現一般利用下列的輔助接口:

 

 sqlite3_aggregate_context()

 sqlite3_result()

 sqlite3_user_data()

 sqlite3_value()

 

SQLite中全部內建的SQL函數接口也是經過這些相同的接口實現的。查看SQLite源代碼,尤爲是date.cfunc.c兩個文件就有許多這方面的例子。

 

4、在VC下使用SQLite

#include "../sqlite3_lib/sqlite3.h"

 

#pragma comment(lib, "../sqlite3_lib/sqlite3.lib")

 

static int _sql_callback(void * notused, int argc, char ** argv, char ** szColName)

{

    int i;

    for ( i=0; i < argc; i++ )

    {

        printf( "%s = %s/n", szColName[i], argv[i] == 0 ? "NUL" : argv[i] );

    }

      

    return 0;

}

 

int main(int argc, char * argv[])

{

    const char * sSQL1 = "create table users(userid varchar(20) PRIMARY KEY, age int, birthday datetime);";

    const char * sSQL2 = "insert into users values('wang',20,'1989-5-4');";

    const char * sSQL3 = "select * from users;";

 

    sqlite3 * db = 0;

    char * pErrMsg = 0;

    int ret = 0;

   

    // 鏈接數據庫

    ret = sqlite3_open("./test.db", &db);

      

    if ( ret != SQLITE_OK )

    {

        fprintf(stderr, "沒法打開數據庫: %s", sqlite3_errmsg(db));

        return(1);

    }

      

    printf("數據庫鏈接成功!/n");

      

    // 執行建表SQL

 

    sqlite3_exec( db, sSQL1, 0, 0, &pErrMsg );

    if ( ret != SQLITE_OK )

    {

        fprintf(stderr, "SQL error: %s/n", pErrMsg);

        sqlite3_free(pErrMsg);

    }

      

    // 執行插入記錄SQL

    sqlite3_exec( db, sSQL2, 0, 0, &pErrMsg);

 

    // 查詢數據表

    sqlite3_exec( db, sSQL3, _sql_callback, 0, &pErrMsg);

 

    // 關閉數據庫

    sqlite3_close(db);

    db = 0;

      

    return 0;

}

 

使用事務

 
    在上面的例子中,咱們向數據庫裏插入了10條數據,而後再從數據庫裏讀出來。細心的你不知道有沒有發現,在執行Insert的時候
,並無使用同一個事 務。在不少狀況下,咱們須要使用事務來保證對數據庫操做的原子性。Sqlite是支持事務的,並且對事務的使用很是簡單:
使用sql語句」begin;」 表示事務開始,」rollback;」表示事務的回滾,」commit;」表示事務的提交。下面咱們對上面例子中的代碼做一下修改,
給Insert操做添 加事務支持:
 
//... ...

bool is_succed = true; sqlite3_exec(conn, "begin;", 0, 0, 0);  //

開啓事務 //添加10條記錄 for (int i = 0; i < 10; i++) {     // 執行SQL     sprintf(sql, "INSERT INTO [test_for_cpp] ([id], [name], [age]) /         VALUES (%d, '%s', %d)", i, "JGood", i);     if (SQLITE_OK != sqlite3_exec(conn, sql, 0, 0, &err_msg))     {         is_succed = false;         break;     } } if (is_succed)     sqlite3_exec(conn, "commit;", 0, 0, 0);  // 提交事務 else     sqlite3_exec(conn, "rollback;", 0, 0, 0);  // 回滾事務 //... ...

 

使用sql參數

 
    基本上,使用sqlite3_open, sqlite3_close, sqlite3_exec這三個函數,
能夠完成大大部分的工做。但還不完善。上面的例子中,都是直接以sql語句的形式來操做數據庫,這樣很容易被注入。因此有必要使用sql參數。
 
sqlite3_prepare
 
sqlite3_bind_*
 
sqlite3_step
 
sqlite3_column_*
 
struct sqlite3_stmt
 
sqlite3_finalize
 
    sqlite3_prepare用來編譯sql語句。sql語句被執行以前,
必須先編譯成字節碼。sqlite3_stmt是一個結構體,表示sql語句 編譯後的字節碼。sqlite3_step用來執行編譯後的sql語句。
sqlite3_bind_*用於將sql參數綁定到sql語句。 sqlite3_column_*用於從查詢的結果中獲取數據。sqlite3_finalize用來釋放sqlite3_stmt對象。代碼最能說明函 數的功能,
下面就用一個例子來演示吧~~
 
// ----------------------------------------------
// http://blog.csdn.net/JGood
 
// sqlite3_prepare, sqlite3_bind_*, sqlite3_step, sqlite3_column_*, sqlite3_column_type
// sqlite3_stmt, sqlite3_finalize, sqlite3_reset
// 查詢
// ----------------------------------------------
sqlite3 *conn = NULL;
sqlite3_stmt *stmt = NULL;
const char *err_msg = NULL;
// 列數據類型
char col_types[][10] = { "", "Integer", "Float", "Text", "Blob", "NULL" };

sqlite3_open("test.db", &conn);
sqlite3_prepare(conn, "SELECT * FROM [test_for_cpp] WHERE [id]>?", -1, &stmt, &err_msg);
sqlite3_bind_int(stmt, 1, 5);

while (SQLITE_ROW == sqlite3_step(stmt))
{
    int col_count = sqlite3_column_count(stmt); // 結果集中列的數量

    const char *col_0_name = sqlite3_column_name(stmt, 0); // 獲取列名
    int id = sqlite3_column_int(stmt, 0);
    int id_type = sqlite3_column_type(stmt, 0); // 獲取列數據類型

    const char *col_2_name = sqlite3_column_name(stmt, 2);
    int age = sqlite3_column_int(stmt, 2);
    int age_type = sqlite3_column_type(stmt, 2);

    const char *col_1_name = sqlite3_column_name(stmt, 1);
    char name[80];
    strncpy(name, (const char *)sqlite3_column_text(stmt, 1), 80);
    int name_type = sqlite3_column_type(stmt, 1);

    // 打印結果
    printf("col_count: %d, %s = %d(%s), %s = %s(%s), %s = %d(%s)/n",
        col_count, col_0_name, id, col_types[id_type], col_2_name, name,
        col_types[name_type], col_1_name, age, col_types[age_type]);
}

sqlite3_finalize(stmt); // 釋放sqlite3_stmt 
sqlite3_close(conn);
這段代碼查詢id號大於5的全部記錄.
其餘函數
 在上面的例子中,還使用了其餘的一些函數,
如:sqlite3_column_count用於獲取結果集中列的數 量;sqlite3_column_name用於獲取列的名稱;
sqlite3_column_type用於獲取列的數據類 型;sqlite3_errcode用於獲取最近一次操做出錯的錯誤代碼;
sqlite3_errmsg用於獲取最近一次操做出錯的錯誤說明。 sqlite的api中還有不少的函數,有了上面的基礎,

相信你經過查詢官方的文檔,能迅速掌握本文未介紹的api

 

 

5、數據庫管理工具

sqlite 管理工具 Sqlite Developer

Sqlite Developer是SharpPlus出品的一款強大數據庫管理軟件。支持對sqlite3數據庫的管理。

下載:http://dl.pconline.com.cn/download/60827.html

 Sqlite Developer 註冊碼http://download.csdn.net/source/2755962

 

常見問題

一、  建立數據
若是不往數據庫裏面添加任何的表,這個數據庫等於沒有創建,不會在硬盤上產生任何文件,若是數據庫已經存在,則會打開這個數據庫。

二、  如何經過sqlite3.dll與sqlite3.def生成sqlite3.lib文件
LIB /DEF:sqlite3.def /machine:IX86

三、  如何查詢當前的編碼的編碼格式
pragma  encoding;

四、  若是刪除了大量數據,而又想縮小數據庫文件佔用的空間,執行 VACUUM 命令
vacuum;

五、  sqlite3_open打開一個數據庫時,若是數據庫不存在就會新生成一個數據庫文件。若是接着執行其餘查詢語句就會失敗,好比sqlite3_prepare,編程中出現明明指定了數據庫並且裏面也有數據,爲何查詢失敗了,主要是數據庫名路徑不對引發的。通常的作法是先檢查數據庫文件是否存在,若是存在就使用sqlite3_open打開數據庫;不然建立一個新的數據庫。

六、  如何創建自動增加字段

聲明爲 INTEGER PRIMARY KEY 的列將會自動增加。

七、SQLite3支持何種數據類型?

NULL

INTEGER

REAL

TEXT

BLOB

但實際上,sqlite3也接受以下的數據類型:

smallint 16 位元的整數。

interger 32 位元的整數。

decimal(p,s) p 精確值和 s 大小的十進位整數,精確值p是指所有有幾個數(digits)大小值 ,s是指小數點後有幾位數。若是沒有特別指定,則系統會設爲 p=5; s=0 。

float 32位元的實數。

double 64位元的實數。

char(n) n 長度的字串,n不能超過 254。

varchar(n) 長度不固定且其最大長度爲 n 的字串,n不能超過 4000。

graphic(n) 和 char(n) 同樣,不過其單位是兩個字元 double-bytes, n不能超過127。 這個形態是爲了支援兩個字元長度的字體,例如中文字。

vargraphic(n) 可變長度且其最大長度爲 n 的雙字元字串,n不能超過 2000。

date 包含了 年份、月份、日期。

time 包含了 小時、分鐘、秒。

timestamp 包含了 年、月、日、時、分、秒、千分之一秒。

八、SQLite容許向一個integer型字段中插入字符串

這是一個特性,而不是一個bug。SQLite不強制數據類型約束。任何數據均可以插入任何列。你能夠向一個整型列中插入任意長度的字符串,向布爾型列中插入浮點數,或者向字符型列中插入日期型值。 在 CREATE TABLE 中所指定的數據類型不會限制在該列中插入任何數據。任何列都可接受任意長度的字符串(只有一種狀況除外: 標誌爲INTEGER PRIMARY KEY的列只能存儲64位整數,當向這種列中插數據除整數之外的數據時,將會產生錯誤。

 

但SQLite確實使用聲明的列類型來指示你所指望的格式。因此,例如你向一個整型列中插入字符串時,SQLite會試圖將該字符串轉換成一個整數。若是能夠轉換,它將插入該整數;不然,將插入字符串。這種特性有時被稱爲 類型或列親和性(type or column affinity).

九、爲何SQLite不容許在同一個表不一樣的兩行上使用0和0.0做主鍵?

主鍵必須是數值類型,將主鍵改成TEXT型將不起做用。

每一行必須有一個惟一的主鍵。對於一個數值型列, SQLite認爲 '0' 和 '0.0' 是相同的, 由於他們在做爲整數比較時是相等的(參見上一問題)。 因此,這樣值就不惟一了。

十、多個應用程序或一個應用程序的多個實例能夠同時訪問同一個數據庫文件嗎?

 

多個進程可同時打開同一個數據庫。多個進程能夠同時進行SELECT 操做,但在任一時刻,只能有一個進程對數據庫進行更改。

 

SQLite 使用讀、寫鎖控制對數據庫的訪問。(在Win95/98/ME等不支持讀、寫鎖的系統下,使用一個機率性的模擬來代替。)但使用時要注意:若是數據庫文件存放於一個NFS文件系統上,這種鎖機制可能不能正常工做。 這是由於 fcntl() 文件鎖在不少NFS上沒有正確的實現。在可能有多個進程同時訪問數據庫的時候,應該避免將數據庫文件放到NFS上。在Windows上,Microsoft的文檔中說:若是使用 FAT 文件系統而沒有運行 share.exe 守護進程,那麼鎖多是不能正常使用的。那些在Windows上有不少經驗的人告訴我:對於網絡文件,文件鎖的實現有好多Bug,是靠不住的。若是他們說的是對的,那麼在兩臺或多臺Windows機器間共享數據庫可能會引發不指望的問題。

 

咱們意識到,沒有其它嵌入式的 SQL 數據庫引擎能象 SQLite 這樣處理如此多的併發。SQLite容許多個進程同時打開一個數據庫,同時讀一個數據庫。當有任何進程想要寫時,它必須在更新過程當中鎖住數據庫文件。但那一般只是幾毫秒的時間。其它進程只需等待寫進程幹完活結束。典型地,其它嵌入式的SQL數據庫引擎同時只容許一個進程鏈接到數據庫。

 

可是,Client/Server數據庫引擎(如 PostgreSQL, MySQL, 或 Oracle)一般支持更高級別的併發,而且容許多個進程同時寫同一個數據庫。這種機制在Client/Server結構的數據庫上是可能的,由於老是有一個單一的服務器進程很好地控制、協調對數據庫的訪問。若是你的應用程序須要不少的併發,那麼你應該考慮使用一個Client/Server 結構的數據庫。但經驗代表,不少應用程序須要的併發,每每比其設計者所想象的少得多。

 

當SQLite試圖訪問一個被其它進程鎖住的文件時,缺省的行爲是返回 SQLITE_BUSY。 能夠在C代碼中使用sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函數調整這一行爲。

十一、SQLite線程安全嗎?

線程是魔鬼(Threads are evil)。 避免使用它們。

SQLite 是線程安全的。因爲不少用戶會忽略咱們在上一段中給出的建議, 咱們作出了這種讓步。可是,爲了達到線程安全,SQLite在編譯時必須將 SQLITE_THREADSAFE 預處理宏置爲1。在Windows和Linux上,已編譯的好的二進制發行版中都是這樣設置的。若是不肯定你所使用的庫是不是線程安全的,能夠調用 sqlite3_threadsafe() 接口找出。

十二、在SQLite數據庫中如何列出全部的表和索引?

若是你運行 sqlite3 命令行來訪問你的數據庫,能夠鍵入 「.tables」來得到全部表的列表。或者,你能夠輸入 「.schema」來看整個數據庫模式,包括全部的表的索引。 輸入這些命令,後面跟一個LIKE模式匹配能夠限制顯示的表。

1三、SQLite數據庫有已知的大小限制嗎?

在 Windows 和 Unix 下,版本 2.7.4的 SQLite 能夠達到 2的41次方字節 (2T 字節)。老版本的爲 2的31 次方字節(2G 字節)。

SQLite 版本 2.8 限制一個記錄的容量爲 1M。SQLite 版本 3.0 則對單個記錄容量沒有限制。

表名、索引表名、視圖名、觸發器名和字段名沒有長度限制。但 SQL 函數的名稱 (由 sqlite3_create_function() API 函數建立) 不得超過 255 個字符。

1四、在SQLite中,VARCHAR字段最長是多少?

SQLite 不強制 VARCHAR 的長度。 你能夠在 SQLITE 中聲明一個 VARCHAR(10),SQLite仍是能夠很高興地容許你放入500個字符。 而且這500個字符是原封不動的,它永遠不會被截斷。

1五、在SQLite中,如何在一個表上添加或刪除一列?

SQLite 有有限地 ALTER TABLE 支持。你可使用它來在表的末尾增長一列,可更改表的名稱。 若是須要對錶結構作更復雜的改變,則必須從新建表。 重建時能夠先將已存在的數據放到一個臨時表中,刪除原表, 建立新表,而後將數據從臨時表中複製回來。

 

如,假設有一個 t1 表,其中有 "a", "b", "c" 三列, 若是要刪除列 c ,如下過程描述如何作:

 

BEGIN TRANSACTION;

CREATE TEMPORARY TABLE t1_backup(a,b);

INSERT INTO t1_backup SELECT a,b FROM t1;

DROP TABLE t1;

CREATE TABLE t1(a,b);

INSERT INTO t1 SELECT a,b FROM t1_backup;

DROP TABLE t1_backup;

COMMIT;

 

1六、如何在Windows下編譯SQLite3
1)先從官網獲取sqlite-amalgamation-3_6_22.zip;

2)接着從官網獲取sqlitedll-3_6_22.zip

下載編譯好的DLL,這裏有咱們須要的sqlite3.def該文件

3)打開VC新建一個「Win32 Dynamic-Link Library」工程,命名爲:sqlite3;

4)在接下來的對話框中選擇"An empty DLL project",點 FINISH->OK;

5)將sqlite-amalgamation-3_6_22文件夾下的sqlite3.h以及sqlite3.c兩個文件複製到工程文件夾下;

       將sqlitedll-3_6_22文件夾下的sqlite3.def該文件複製到工程文件夾下;

6)在工程的Source Files中添加sqlite3.c文件;

7)在工程的Include Files中添加sqlite3.h文件;

8)在工程的Resource Files中添加sqlite3.def文件;

9)針對以下問題:

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_database_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_database_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_origin_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_origin_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_table_name

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_column_table_name16

sqlite3.def : error LNK2001: unresolved external symbol sqlite3_table_column_metadata

Debug/sqlite3.lib : fatal error LNK1120: 7 unresolved externals

在菜單【Project】-【Settings…】-【C/C++】標籤下的Category【General】下

Preprocessor definitions下:

新增2個編譯選項,分別是:

THREADSAFE

SQLITE_ENABLE_COLUMN_METADATA

10)往工程中添加sqlite3.def文件就是爲生成sqlite3.lib文件;

sqlite3.lib是與sqlite3.dll動態連接庫文件一塊兒提供給軟件開發者的;

11)解決Windows下的編譯警告
e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'long *'

e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 1

e:/sqlite/code/sqlite3/sqlite3.c(15385) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 2

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'long *'

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 1

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4022: 'InterlockedCompareExchange' : pointer mismatch for actual parameter 3

e:/sqlite/code/sqlite3/sqlite3.c(15403) : warning C4047: '==' : 'void *' differs in levels of indirection from 'const int '

e:/sqlite/code/sqlite3/sqlite3.c(65536) : warning C4049: compiler limit : terminating line number emission

warning C4761: integral size mismatch in argument; conversion supplied

warning C4761: integral size mismatch in argument; conversion supplied

warning C4761: integral size mismatch in argument; conversion supplied

 

VC2005 + SQLite 3.6.3 編譯、測試開發

http://blog.csdn.net/Dreamcode/archive/2009/08/21/4467277.aspx

 

參考資料:

sqlite 中文社區:http://www.sqlite.com.cn/

sqlite 官方網站:http://www.sqlite.org/

相關文章
相關標籤/搜索