SQLite相关知识
sqlite3_exec(db, “insert into name values ‘lxkxf', ‘24'; ”, 0, 0, &zErrMsg);
將會重復的打開關閉數據庫文件100萬次,所以速度當然會很慢。因此對于這種情況我們應該使用“事務”。
具體方法如下:在執行SQL語句之前和SQL語句執行完畢之后加上
rc = sqlite3_exec(db, "BEGIN;", 0, 0, &zErrMsg);
//執行SQL語句
rc = sqlite3_exec(db, "COMMIT;", 0, 0, &zErrMsg);
這樣SQLite將把全部要執行的SQL語句先緩存在內存當中,然后等到COMMIT的時候一次性的寫入數據庫,這樣數據庫文件只被打開關閉了一次,效率自然大大的提高。有一組數據對比:
測試1: 1000 INSERTs
CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
SQLite 2.7.6:
13.061
SQLite 2.7.6 (nosync):
0.223
測試2: 使用事務 25000 INSERTs
BEGIN;
CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two');
... 24997 lines omitted
INSERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine');
INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six');
COMMIT;
SQLite 2.7.6:
0.914
SQLite 2.7.6 (nosync):
0.757
可見使用了事務之后卻是極大的提高了數據庫的效率。但是我們也要注意,使用事務也是有一定的開銷的,所以對于數據量很小的操作可以不必使用,以免造成而外的消耗。
char?buf[256];
int?i?=?1;
sprintf(buf,?"insert?into?tbl?values(%d,?'%s',%d,?%d);?",??i,?"",?i,?1); ?//注意帶單引號的地方
然后傳入?buf?.
--------------------------------------
? ??前一段時間用sqlite數據庫做公交查詢系統,在使用sqlite數據庫時,遇到了一些問題,現在總結一下,與大家分享:
1 ??? ?sqlite數據庫中的主鍵必須是Integer類型的,其他類型的絕對不行,假如在一個表中沒有設置主鍵,當插入數據時,是存在一個看不見的默認主鍵自增長的。假如你聲明表中的主鍵為Integer ?primary ?key類型,每當你在一行中插入一個null值時,null自動被轉換為一個比該行中最大值大1的一個整數,如果表是空的話,將會是1。(如果是最大可能值9223372036854775807,鍵值將是隨機未使用的數。)
2 ??SQLite允許向一個integer型字段中插入字符串,?任何數據都可以插入任何列。你可以向一個整型列中插入任意長度的字符串,向布爾型列中插入浮點數,或者向字符型列中插入日期型值。 在 CREATE TABLE 中所指定的數據類型不會限制在該列中插入任何數據。任何列均可接受任意長度的字符串(只有一種情況除外: 標志為INTEGER PRIMARY KEY的列只能存儲64位整數,當向這種列中插數據除整數以外的數據時,將會產生錯誤。
3 ?SQLite 不強制 VARCHAR 的長度。 你可以在 SQLITE 中聲明一個 VARCHAR(10),SQLite還是可以很高興地允許你放入500個字符。 并且這500個字符是原封不動的,它永遠不會被截斷。
--------------------------------------
SQLITE3中INSERT語句的注意事項
??if(!(rv?=?sqlite3_open(szDbname,?&db)))??
? {?????????
? ? ? sprintf(sql,?"DELETE?FROM?problem_people?WHERE?fpid?=?%d;",?m_iRecordID);??
? ? ?GB2312_2_UTF8(buf,?512,?sql,?strlen(sql));??
? ? ? rv?=?sqlite3_prepare(db,?buf,?strlen(buf),?&stmt,?NULL);??
?
? ? ??if((rv?=?sqlite3_step(stmt))?==?SQLITE_DONE)??
? ? ? ?{??
? ? ? ? ??int?iCount?=?m_listPerson.GetItemCount();??
? ? ? ? ? ?for(int?i?=?0;?i?<?iCount;?++?i)??
? ? ? ? ? ?{??
? ? ? ? ? ? ?CString?sName?=?m_listPerson.GetItemText(i,?0);??
? ? ? ? ? ? CString?sScore?=?m_listPerson.GetItemText(i,?1);??
? ? ? ? ? ? ?CString?sNo;??
? ? ? ? ? ? ? sNo.Format(L"%d",?i?+?1);??
? ? ? ? ? ? sprintf(sql,?"INSERT?INTO?problem_people?VALUES(?,%d,'%S','%S','%S',null,null);",???
? ? ? ? ? ? ? m_iRecordID,?sNo,?sName,?sScore);??
? ? ? ? ? ? GB2312_2_UTF8(buf,?512,?sql,?strlen(sql));??
? ? ? ? ? ?rv?=?sqlite3_prepare(db,?buf,?strlen(buf),?&stmt,?NULL);??????
? ? ? ? ? ?rv?=?sqlite3_step(stmt);??
? ? ? ? ?}??
? ? ? }??
?
SQLITE3的INSERT語句由于要插入數值,一般使用通配符'?',然后將每個問號和數據一一綁定。
如上例中,我們可以用
1.? INSERT?INTO?problem_people?VALUES(?,%d,?,?,?,null,null);"??
代替sprintf函數,而后使用sqlite3_bind_text等函數進行對應的綁定。
在原例中,由于插入數據為字符串,該字段需要用單引號括起,而在通配符例子中無需使用單引號。
值得注意的是,當字符串為數字時,sql語句會自動轉換數字為字符串,也無需使用單引號。
如果你應該使用單引號,而沒有寫上去,sqlite會告訴你SQLITE3_MISUSE的錯誤。這說明sql語句有誤。
還有最后一個問題。在原例中,我并沒有將第一個問號匹配,這是因為sqlite中有一項默認規定,只要INTEGER字段作為主鍵,插入時將其設為?就能做到自增,這是一項挺方便的設定。
--------------------------------------------------------------
SQLite教程(360doc)--20110303
1:sqlite常用接口
?
2個重要結構體和5個主要函數:
?
sqlite3 ? ? ? ? ? ? ? *pdb, 數據庫句柄,跟文件句柄FILE很類似
?
sqlite3_stmt ? ? ?*stmt, 這個相當于ODBC的Command對象,用于保存編譯好的SQL語句
?
sqlite3_open(), ? 打開數據庫
?
sqlite3_exec(), ? 執行非查詢的sql語句
?
sqlite3_prepare(), 準備sql語句,執行select語句或者要使用parameter bind時,用這個函數(封裝了sqlite3_exec).
?
Sqlite3_step(), 在調用sqlite3_prepare后,使用這個函數在記錄集中移動。
?
Sqlite3_close(), 關閉數據庫文件
?
還有一系列的函數,用于從記錄集字段中獲取數據,如
?
sqlite3_column_text(), 取text類型的數據。
?
sqlite3_column_blob(),取blob類型的數據
?
sqlite3_column_int(), 取int類型的數據
…
---------------------------
SQlite 字符編碼
SQLite按照下面四種字符編碼保存數據,相應的語句如下:PRAGMA encoding = "UTF-8";?
PRAGMA encoding = "UTF-16";?
PRAGMA encoding = "UTF-16le";?
PRAGMA encoding = "UTF-16be";
使用SQLite3.exe,在字符界面下,使用insert語句插入的字符,默認是GB2312編碼的, 但是使用like查找記錄時,會有問題,如果你肯定不使用like語句,可以不需要轉換成標準的字符編碼保存 ,建議還 是統一使用默認UTF-8保存數據。 -----------------------------------------------------------
?2:sqlite數據類型介紹
?? ? 在進行數據庫Sql操作之前,首先有個問題需要說明,就是Sqlite的數據類型,和其他的數據庫不同,Sqlite支持的數據類型有他自己的特色,這個特色有時會被認為是一個潛在的缺點,但是這個問題并不在我們的討論范圍之內。
大多數的數據庫在數據類型上都有嚴格的限制,在建立表的時候,每一列都必須制定一個數據類型,只有符合該數據類型的數據可以被保存在這一列當 中。而在Sqlite 2.X中,數據類型這個屬性只屬于數據本生,而不和數據被存在哪一列有關,也就是說數據的類型并不受數據列限制(有一個例外:INTEGER PRIMARY KEY,該列只能存整型數據)。
但是當Sqlite進入到3.0版本的時候,這個問題似乎又有了新的答案,Sqlite的開發者開始限制這種無類型的使用,在3.0版本當中, 每一列開始擁有自己的類型,并且在數據存入該列的時候,數據庫會試圖把數據的類型向該類型轉換,然后以轉換之后的類型存儲。當然,如果轉換被認為是不可行 的,Sqlite仍然會存儲這個數據,就像他的前任版本一樣。
舉個例子,如果你企圖向一個INTEGER類型的列中插入一個字符串,Sqlite會檢查這個字符串是否有整型數據的特征, 如果有而且可以被數據庫所識別,那么該字符串會被轉換成整型再保存,如果不行,則還是作為整型存儲。
?
總的來說,所有存在Sqlite 3.0版本當中的數據都擁有以下之一的數據類型:
空(NULL):該值為空
整型(INTEGEER):有符號整數,按大小被存儲成1,2,3,4,6或8字節。
實數(REAL):浮點數,以8字節指數形式存儲。
文本(TEXT):字符串,以數據庫編碼方式存儲(UTF-8, UTF-16BE 或者 UTF-16-LE)。
BLOB:BLOB數據不做任何轉換,以輸入形式存儲。
?
ps: 在關系數據庫中,CLOB和BLOB類型被用來存放大對象。BOLB表示二進制大對象,這種數據類型通過用來保存圖片,圖象,視頻等。CLOB表示字符大對象,能夠存放大量基于字符的數據。
?
對應的,對于數據列,同樣有以下的數據類型:
TEXT
NUMERIC
INTEGER
REAL
NONE
數據列的屬性的作用是確定對插入的數據的轉換方向:
TEXT 將數據向文本進行轉換,對應的數據類型為NULL,TEXT 或 BLOB
NUMERIC 將數據向數字進行轉換,對應的數據類型可能為所有的五類數據,當試圖存入文本 時將執行向整型或浮點類型的轉換(視具體的數值而定),轉換若不可行,則保留文本類型存儲,NULL或BLOB不做變化
INTEGER 將數據向整型轉換,類似于NUMERIC,不同的是沒有浮點標志的浮點數將轉換為整型保存
REAL 將數據向浮點數類型轉換,類似于NUMERIC,不同的是整數將轉換為浮點數保存
NULL 不做任何轉換的數據列類型
?
實例代碼如下,
附件工程可直接編譯,例子使用了blob數據類型。
#include "sqlite3.h" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//包含一個頭文件就可以使用所以sqlite的接口了
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#pragma comment(lib, "sqlite.lib") //我把sqlite編譯成了一個靜態的lib文件。
void ? ? ? createdb();
void ? ? ? querydb();
int ? ? ? ? main()
{
?? ? ? ? ? ?createdb();
?? ? ? ? ? ?querydb();
?? ? ? ? ? ?return 0;
}
void ? ? ? createdb()
{
?? ? ? ? ? ?int ? ? ? ? ? ? ? ? ? ? ret;
?? ? ? ? ? ?sqlite3 ? ? ? ? ? ? ? *pdb = 0;
?? ? ? ? ? ?sqlite3_stmt ? ? ?*stmt = 0;
?? ? ? ? ? ?char ? ? ? ? ? ? ? ? ?*error = 0;
?? ? ? ? ? ?char ? ? ? ? ? ? ? ? ?*sql = "insert into table1 values('value11',:aaa)";
?? ? ? ? ? ?int ? ? ? ? ? ? ? ? ? ? index;
?? ? ? ? ? ?static void ? ? ? ? ?*value = "asdfadsfasdfjasdfjaksdfaskjdfakdsfaksfja";
?? ? ? ? ? ?ret = sqlite3_open("db1.sdb", &pdb); ? ? ? ? ? ? ? ? ? ?//打開數據庫,跟打開文本文件一樣
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?ret = sqlite3_exec(pdb, "create table table1(col1 char(20), col2 BLOB)", 0,0, &error );
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?ret = sqlite3_prepare(pdb, sql,strlen(sql), &stmt, &error);
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?index = sqlite3_bind_parameter_index(stmt, ":aaa");
?? ? ? ? ? ?ret = sqlite3_bind_blob(stmt, index, value, strlen(value), SQLITE_STATIC);
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?ret = sqlite3_step(stmt);
??? ? ? ? ? ?if( ret != SQLITE_DONE )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?sqlite3_close(pdb); ? ? ? ?
}
void ? ? ? querydb()
{
?? ? ? ? ? ?int ? ? ? ? ? ? ? ? ? ? ret;
?? ? ? ? ? ?sqlite3 ? *pdb = 0;
?? ? ? ? ? ?sqlite3_stmt ? ? ?*pstmt = 0;
?? ? ? ? ? ?char ? ? ?*error = 0;
?? ? ? ? ? ?char ? ? ?*sql = "select * from table1";
?? ? ? ? ? ?int ? ? ? ? ? ? ? ? ? ? len;
?? ? ? ? ? ?int ? ? ? ? ? ? ? ? ? ? i;
?? ? ? ? ? ?char ? ? ?*name;
?? ? ? ? ? ?void ? ? ? *value;
?? ? ? ? ? ?ret = sqlite3_open("db1.sdb", &pdb);
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?ret = sqlite3_prepare(pdb, sql, strlen(sql), &pstmt, &error);
?? ? ? ? ? ?if( ret != SQLITE_OK )
?? ? ? ? ? ? ? ? ? ? ? ?return;
?? ? ? ? ? ?while( 1 )
?? ? ? ? ? ?{
?? ? ? ? ? ? ? ? ? ? ? ?ret = sqlite3_step(pstmt);
?? ? ? ? ? ? ? ? ? ? ? ?if( ret != SQLITE_ROW )
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
?? ? ? ? ? ? ? ? ? ? ? ?name = sqlite3_column_text(pstmt, 0);
?? ? ? ? ? ? ? ? ? ? ? ?value = sqlite3_column_blob(pstmt, 1);
?? ? ? ? ? ? ? ? ? ? ? ?len = sqlite3_column_bytes(pstmt,1 );
?? ? ? ? ? ?}
}
?
實例二:SQLite中如何用api操作blob類型的字段
?
?? 在實際的編程開發當中我們經常要處理一些大容量二進制數據的存儲,如圖片或者音樂等等。對于這些二進制數據(blob字段)我們不能像處理普通的文本那樣 簡單的插入或者查詢,為此SQLite提供了一組函數來處理這種BLOB字段類型。下面的代碼演示了如何使用這些API函數。
?
首先我們要建立一個數據庫:
sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);
?
//由于mmmm.rar是一個二進制文件,所以要在使用insert語句時先用?號代替
?? ? sqlite3_prepare(db, "insert into list values ('mmmm.rar',?);", -1, &stat, 0);
?? ? FILE *fp;
?? ? long filesize = 0;
?? ? char * ffile;
??? ? fp = fopen("mmmm.rar", "rb");
??? ? if(fp != NULL)
?? ? {
?? ? ? ? //計算文件的大小
?? ? ? ? fseek(fp, 0, SEEK_END);
?? ? ? ? filesize = ftell(fp);
?? ? ? ? fseek(fp, 0, SEEK_SET);
?
?? ? ? ? //讀取文件
?? ? ? ? ffile = new char[filesize+1];
?? ? ? ? size_t sz = fread(ffile, sizeof(char), filesize+1, fp);
?? ? ? ? ? ??
?? ? ? ? fclose(fp);
?? ? }
?
?? ? //將文件數據綁定到insert語句中,替換“?”部分
?? ? sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);
?? ?
//執行綁定之后的SQL語句
?? ? sqlite3_step(stat);
這時數據庫當中已經有了一條包含BLOB字段的數據。接下來我們要讀取這條數據:
?? ?
?? ? //選取該條數據
?? ? sqlite3_prepare(db, "select * from list;", -1, &stat, 0);
?? ? sqlite3_step(stat);
//得到紀錄中的BLOB字段
const void * test = sqlite3_column_blob(stat, 1);
//得到字段中數據的長度
?? ? int size = sqlite3_column_bytes(stat, 1);
?? ?
?? ? //拷貝該字段
?? ? sprintf(buffer2, "%s", test);
此時可以將buffer2寫入到文件當中,至此BLOB數據處理完畢。
?
實例三:sqlite 中用blob存儲圖片和取出圖片
?
#include<iostream>
#include<string>
#include<sqlite3.h>
using namespace std;
int main()
{
?? ? ? ?sqlite3 *db;
?sqlite3_stmt *stat;
?char *zErrMsg = 0;
?char buffer2[1024]="0";
?
?sqlite3_open("./MetaInfo.db", &db);
?? ?int result;
?? ? if(result)
?? ? ?{
?? ? ? ? cout<<"Open the database sqlite.db failed"<<endl;
?? ? ? }
????? ? else
?? ? ? ? ?cout<<"Open the database sqlite.db sucessfully"<<endl;
?sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);
?sqlite3_prepare(db, "insert into list values ('./data/2.bmp',?);", -1, &stat, 0);
??FILE *fp;
?long filesize = 0;
?char * ffile;
?fp = fopen("./data/2.bmp", "rb");
?if(fp != NULL)
?{
??fseek(fp, 0, SEEK_END);
??filesize = ftell(fp);
??fseek(fp, 0, SEEK_SET);
??ffile = new char[filesize+1];
??size_t sz = fread(ffile, sizeof(char), filesize+1, fp);
?????fclose(fp);
?}
?sqlite3_bind_blob(stat, 1, ffile, filesize, NULL);
?sqlite3_step(stat);
?sqlite3_prepare(db, "select * from list;", -1, &stat, 0);
?sqlite3_step(stat);
?const void * test = sqlite3_column_blob(stat, 1);
?int size = sqlite3_column_bytes(stat, 1);
?sprintf(buffer2, "%s", test);
?FILE *fp2;
?fp2 = fopen("outfile.png", "wb");
?if(fp2 != NULL)
?{
??size_t ret = fwrite(test, sizeof(char), size, fp2);
??fclose(fp2);
?}
?delete(ffile);
?sqlite3_finalize(stat);
?sqlite3_close(db);
?? return 0;
}
?? ? SQLite3是SQLite一個全新的版本,它雖然是在SQLite 2.8.13的代碼基礎之上開發的,但是使用了和之前的版本不兼容的數據庫格式和API. SQLite3是為了滿足以下的需求而開發的:
?
支持UTF-16編碼.
用戶自定義的文本排序方法.
可以對BLOBs字段建立索引.
因此為了支持這些特性我改變了數據庫的格式,建立了一個與之前版本不兼容的3.0版. 至于其他的兼容性的改變,例如全新的API等等,都將在理論介紹之后向你說明,這樣可以使你最快的一次性擺脫兼容性問題.
?
3.0版的和2.X版的API非常相似,但是有一些重要的改變需要注意. 所有API接口函數和數據結構的前綴都由"sqlite_"改為了"sqlite3_". 這是為了避免同時使用SQLite 2.X和SQLite 3.0這兩個版本的時候發生鏈接沖突.
?
由于對于C語言應該用什么數據類型來存放UTF-16編碼的字符串并沒有一致的規范. 因此SQLite使用了普通的void* 類型來指向UTF-16編碼的字符串. 客戶端使用過程中可以把void*映射成適合他們的系統的任何數據類型.
?
2.0 C/C++ 接口
SQLite 3.0一共有83個API函數,此外還有一些數據結構和預定義(#defines). (完整的API介紹請參看另一份文檔.) 不過你們可以放心,這些接口使用起來不會像它的數量所暗示的那么復雜. 最簡單的程序仍然使用三個函數就可以完成: sqlite3_open(), sqlite3_exec(), 和 sqlite3_close(). 要是想更好的控制數據庫引擎的執行,可以使用提供的sqlite3_prepare()函數把SQL語句編譯成字節碼,然后在使用 sqlite3_step()函數來執行編譯后的字節碼. 以sqlite3_column_開頭的一組API函數用來獲取查詢結果集中的信息. 許多接口函數都是成對出現的,同時有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() 函數返回一個整數錯誤代碼,而不是像第二版中一樣返回一個指向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()接口返回的數據類型來獲取數據. 數據類型不同時軟件將自動轉換.
?
總結
以上是生活随笔為你收集整理的SQLite相关知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不删除旧版本java_Linux 卸载旧
- 下一篇: 为什么你应该尝试全栈