小巧、快速、可靠
任選三項

注意:此文件於 2004 年撰寫,作為協助程式設計師從 SQLite 版本 2 轉移到 SQLite 版本 3 的指南。此文件中的資訊基本上仍然正確,但多年來已進行許多變更和增強。我們建議改用下列文件

SQLite 版本 3 的 C/C++ 介面

1.0 概觀

SQLite 版本 3.0 是 SQLite 的新版本,源自 SQLite 2.8.13 程式碼庫,但具有不兼容的檔案格式和 API。SQLite 版本 3.0 是為了滿足對下列功能的需求而建立的

必須轉移到版本 3.0 才能實作這些功能,因為每個功能都需要對資料庫檔案格式進行不兼容的變更。其他不兼容的變更,例如清理 API,則同時在理論上進行,因為最好一次解決所有不兼容的變更。

版本 3.0 的 API 類似於版本 2.X 的 API,但有一些重要的變更。最明顯的是,所有 API 函式和資料結構開頭的「sqlite_」前綴已變更為「sqlite3_」。這可避免兩個 API 之間的混淆,並允許同時連結到 SQLite 2.X 和 SQLite 3.0。

對於 UTF-16 字串的 C 資料類型應該是什麼,目前尚未達成共識。因此,SQLite 使用 void* 的通用類型來參照 UTF-16 字串。用戶端軟體可以將 void* 轉換為適合其系統的任何資料類型。

2.0 C/C++ 介面

SQLite 3.0 的 API 包含 83 個獨立函式,以及多個資料結構和 #defines。(完整的 API 參考 以獨立文件提供。)幸運的是,介面的複雜度遠低於其規模所暗示的。簡單的程式仍然可以使用只有 3 個函式:sqlite3_open()sqlite3_exec()sqlite3_close()。使用 sqlite3_prepare_v2() 將 SQLite 陳述式編譯成位元組碼,以及使用 sqlite3_step() 執行該位元組碼,可以更進一步控制資料庫引擎的執行。函式家族的名稱以 sqlite3_column_ 開頭,用於擷取查詢結果集的資訊。許多介面函式成對出現,同時具有 UTF-8 和 UTF-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() 常式會傳回整數錯誤碼,而不是版本 2 介面所傳回的 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 表示的主機原生位元組順序的錯誤訊息。

SQLite 版本 3 的錯誤代碼與版本 2 相同。如下所示

#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() 函數的運作方式與 SQLite 版本 2 中的運作方式非常類似。第二個參數中指定的零個或多個 SQL 陳述式會編譯並執行。查詢結果會傳回呼叫函式。

在 SQLite 版本 3 中,sqlite3_exec 常式只是準備好的陳述式介面的呼叫包裝器。

   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 陳述式編譯成位元組碼以供稍後執行。此介面現在是存取資料庫的首選方式。

SQL 陳述式是 sqlite3_prepare() 的 UTF-8 字串。sqlite3_prepare16() 的運作方式相同,但它預期 UTF-16 字串作為 SQL 輸入。輸入字串中只會編譯第一個 SQL 陳述式。如果有的話,第五個參數會填入輸入字串中下一個(未編譯)SQLite 陳述式的指標。sqlite3_finalize() 常式會取消配置準備好的 SQL 陳述式。在資料庫可以關閉之前,必須取消配置所有準備好的陳述式。sqlite3_reset() 常式會重設準備好的 SQL 陳述式,以便可以再次執行。

SQL 敘述可以包含 "?" 或 "?nnn" 或 ":aaa" 形式的令牌,其中 "nnn" 是整數,而 "aaa" 是識別碼。此類令牌代表未指定的文字值(或「萬用字元」),稍後會由 sqlite3_bind 介面填入。每個萬用字元都有一個相關聯的數字,它是其在敘述中的順序,或在 "?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 敘述中的萬用字元。未繫結的萬用字元會解釋為 NULL。sqlite3_reset() 不會重設繫結。但在 sqlite3_reset() 之後,萬用字元可以重新繫結到新的值。

在 SQL 敘述已準備好(且選擇性繫結)之後,使用以下方式執行

   int sqlite3_step(sqlite3_stmt*);

如果 sqlite3_step() 常式傳回 SQLITE_ROW,表示它傳回結果集的單一行,或如果執行已完成(正常或由於錯誤),則傳回 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_v2() 之後隨時呼叫。sqlite3_data_count() 的作用類似於 sqlite3_column_count(),但它僅在 sqlite3_step() 之後才有效。如果對 sqlite3_step() 的前一次呼叫傳回 SQLITE_DONE 或錯誤碼,則 sqlite3_data_count() 會傳回 0,而 sqlite3_column_count() 會繼續傳回結果集中欄位的數目。

使用其他 sqlite3_column_***() 函數檢查傳回的資料,所有函數都將欄位編號作為其第二個參數。欄位從左到右以 0 為索引。請注意,這與從 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() 傳回類型為 BLOB 的欄位中的位元組數,或 UTF-8 編碼的 TEXT 字串中的位元組數。sqlite3_column_bytes16() 對 BLOB 傳回相同的值,但對 TEXT 字串傳回 UTF-16 編碼中的位元組數。sqlite3_column_blob() 傳回 BLOB 資料。sqlite3_column_text() 傳回 TEXT 資料作為 UTF-8。sqlite3_column_text16() 傳回 TEXT 資料作為 UTF-16。sqlite3_column_int() 傳回主機電腦原生整數格式中的 INTEGER 資料。sqlite3_column_int64() 傳回 64 位元 INTEGER 資料。最後,sqlite3_column_double() 傳回浮點資料。

不需要以 sqlite3_column_type() 指定的格式擷取資料。如果要求不同的格式,資料會自動轉換。

資料格式轉換會使先前呼叫 sqlite3_column_blob()、sqlite3_column_text() 和/或 sqlite3_column_text16() 傳回的指標失效。指標可能會在以下情況下失效

請注意,UTF-16be 和 UTF-16le 之間的轉換總是就地進行,且不會使先前的指標失效,儘管先前指標指向的緩衝區內容當然會被修改。其他類型的轉換在可能的情況下會就地進行,但有時無法進行,在這些情況下,先前的指標會失效。

最安全且最容易記住的政策是:假設任何結果來自

會因後續呼叫 這表示您應在呼叫 sqlite3_column_blob()、sqlite3_column_text() 或 sqlite3_column_text16() 之前,始終呼叫 sqlite3_column_bytes() 或 sqlite3_column_bytes16()。

2.3 使用者定義函式

可以使用下列常式建立使用者定義函式

   typedef struct sqlite3_value sqlite3_value;
   int sqlite3_create_function(
     sqlite3 *,
     const char *zFunctionName,
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   int sqlite3_create_function16(
     sqlite3*,
     const void *zFunctionName,
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   #define SQLITE_UTF8     1
   #define SQLITE_UTF16    2
   #define SQLITE_UTF16BE  3
   #define SQLITE_UTF16LE  4
   #define SQLITE_ANY      5

nArg 參數指定函式的引數數量。值 0 表示允許任何數量的引數。eTextRep 參數指定此函式引數預期的文字值表示形式。此參數的值應為上述定義的參數之一。SQLite 版本 3 允許使用不同的文字表示形式來實作相同函式的多個實作。資料庫引擎會選擇需要最少文字轉換的函式。

一般函式只指定 xFunc,並將 xStep 和 xFinal 設定為 NULL。聚合函式指定 xStep 和 xFinal,並將 xFunc 設定為 NULL。沒有單獨的 sqlite3_create_aggregate() API。

函數名稱以 UTF-8 指定。另一個 sqlite3_create_function16() API 的運作方式與 sqlite_create_function() 相同,只不過函數名稱以 UTF-16 主機位元組順序指定。

請注意,函數的參數現在是指向 sqlite3_value 結構的指標,而不是指向字串的指標,如同 SQLite 版本 2.X。下列常式用於從這些「值」中擷取有用的資訊

   const void *sqlite3_value_blob(sqlite3_value*);
   int sqlite3_value_bytes(sqlite3_value*);
   int sqlite3_value_bytes16(sqlite3_value*);
   double sqlite3_value_double(sqlite3_value*);
   int sqlite3_value_int(sqlite3_value*);
   long long int sqlite3_value_int64(sqlite3_value*);
   const unsigned char *sqlite3_value_text(sqlite3_value*);
   const void *sqlite3_value_text16(sqlite3_value*);
   int sqlite3_value_type(sqlite3_value*);

函數實作使用下列 API 來取得內容和回報結果

   void *sqlite3_aggregate_context(sqlite3_context*, int nbyte);
   void *sqlite3_user_data(sqlite3_context*);
   void sqlite3_result_blob(sqlite3_context*, const void*, int n, void(*)(void*));
   void sqlite3_result_double(sqlite3_context*, double);
   void sqlite3_result_error(sqlite3_context*, const char*, int);
   void sqlite3_result_error16(sqlite3_context*, const void*, int);
   void sqlite3_result_int(sqlite3_context*, int);
   void sqlite3_result_int64(sqlite3_context*, long long int);
   void sqlite3_result_null(sqlite3_context*);
   void sqlite3_result_text(sqlite3_context*, const char*, int n, void(*)(void*));
   void sqlite3_result_text16(sqlite3_context*, const void*, int n, void(*)(void*));
   void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
   void *sqlite3_get_auxdata(sqlite3_context*, int);
   void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));

2.4 使用者定義的排序規則

下列常式用於實作使用者定義的排序規則

   sqlite3_create_collation(sqlite3*, const char *zName, int eTextRep, void*,
      int(*xCompare)(void*,int,const void*,int,const void*));
   sqlite3_create_collation16(sqlite3*, const void *zName, int eTextRep, void*,
      int(*xCompare)(void*,int,const void*,int,const void*));
   sqlite3_collation_needed(sqlite3*, void*, 
      void(*)(void*,sqlite3*,int eTextRep,const char*));
   sqlite3_collation_needed16(sqlite3*, void*,
      void(*)(void*,sqlite3*,int eTextRep,const void*));

sqlite3_create_collation() 函數指定排序規則名稱和比較函數來實作該排序規則。比較函數僅用於比較文字值。eTextRep 參數是 SQLITE_UTF8、SQLITE_UTF16LE、SQLITE_UTF16BE 或 SQLITE_ANY 之一,用於指定比較函數運作的文字表示法。對於 UTF-8、UTF-16LE 和 UTF-16BE 文字表示法,相同的排序規則可以有不同的比較函數。sqlite3_create_collation16() 的運作方式與 sqlite3_create_collation() 相同,只不過排序規則名稱以 UTF-16 主機位元組順序指定,而不是以 UTF-8 指定。

sqlite3_collation_needed() 常式註冊一個回呼,如果資料庫引擎遇到未知的排序規則,它會呼叫此回呼。回呼可以查詢適當的比較函數,並視需要呼叫 sqlite_3_create_collation()。回呼的第四個參數是 UTF-8 中的排序規則名稱。對於 sqlite3_collation_need16(),回呼會以 UTF-16 主機位元組順序傳送排序規則名稱。

此頁面最後修改於 2022-01-08 05:02:57 UTC