1、sqlite之C介面簡介
1.1 sqlite3_open
int sqlite3_open (
const char *filename, /* Database filename (UTF-8) */ /* 資料庫將採用UTF-8的編碼方式,sqlite3_open16採用UTF-16的編碼方式 */
sqlite3 **ppDb /* OUT: SQLite db handle */ /* 資料庫連線物件 */
):
開啟一個sqlite資料庫檔案的連線並且返回一個資料庫連線物件。
First: 資料庫名。
Second: 一個資料庫連線控制程式碼被返回到這個引數。
Return: 如果執行成功,則返回SQLITE_OK,否則返回一個錯誤碼。
1.2 sqlite3_prepare_v2
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */ /* 成功開啟的資料庫控制程式碼 */
const char *zSql, /* SQL statement, UTF-8 encoded */ /* UTF8編碼的 SQL 語句 */
int nByte, /* Maximum length of zSql in bytes. */ /* 引數 sql 的位元組數, 包含 ` ` */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */ /* 輸出:預編譯語句控制程式碼 */
const char **pzTail /* OUT: Pointer to unused portion of zSql */ /* 輸出:指向 sql 語句中未使用的部分 */
);
這個函式將sql文字轉換成一個準備語句(prepared statement)物件,同時返回這個物件的指標。
First: 資料庫連線控制程式碼。
Second: 將要被編譯的SQL語句。
Third: 如果nByte為負值(-1),則函式取出zSql中從開始到第一個0終止符的內容;若為正值,那麼它就是這個函式能從zSql中讀取的位元組數的最大值;若為0,不會產生SQL語句。有一個更好的做法是:把nbytes的值設為該字串的長度(包含` `), 這樣可以避免 SQLite 複製該字串的一份拷貝, 以提高程式的效率.
Forth: 指向一個被編譯的語句控制程式碼,它可被sqlite3_step執行。執行錯誤或者輸入的zSql為空字元,*ppStmt為NULL,用sqlite3_finalize來釋放它。
Fifth: 上面提到zSql在遇見終止符或者是達到設定的nByte之後結束,假如zSql還有剩餘的內容,那麼這些剩餘的內容被存放到pZTail中,不包括終止符。如果 pszTail 不為 NULL, 則 pszTail 指向 sql 中第一個被傳入的 SQL 語句的結尾. 該函式只編譯 sql 的第一個語句, 所以 pszTail 指向的內容則是未被編譯的.
Return: 如果執行成功,則返回SQLITE_OK,否則返回一個錯誤碼。
1.3 sqlite3_step
int sqlite3_step(sqlite3_stmt *stmt);
呼叫一次或者多次被編譯的語句控制程式碼。
Return: SQLITE_BUSY,SQLITE_DONE,SQLITE_ROW,SQLITE_ERROR,SQLITE_MISUSE。
SQLITE_BUSY: 忙碌. 資料庫引擎無法鎖定資料去完成其工作. 但可以多次嘗試.
SQLITE_DONE: 完成. sql 語句已經被成功地執行.在呼叫 sqlite_reset() 之前,當前預編譯的語句不應該被sqlite3_step()再次呼叫.
SQLITE_ROW: 查詢時產生了結果. 此時可以通過相關的”資料訪問函式(column access functions)”來取得資料. sqlite3_step()可再一次呼叫將取得下一條查詢結果.
SQLITE_ERROR: 發生了錯誤. 此時可以通過 sqlite3_errmmsg() 取得相關的錯誤資訊. sqlite3_step() 不能被再次呼叫.
SQLITE_MISUSE: 不正確的庫的使用. 該函式使用不當.
1.4 sqlite3_reset
int sqlite3_reset (sqlite3_stmt *stmt);
sqlite3_reset用於重置一個準備語句物件到它的初始狀態,然後準備被重新執行。所有sql語句變數使用sqlite3_bind_XXX繫結值,使用sqlite3_clear_bindings清除這些繫結。Sqlite3_reset介面重置準備語句到它程式碼開始的時候。sqlite3_reset並不改變在準備語句上的任何繫結值,那麼這裡猜測,可能是語句在被執行的過程中發生了其他的改變,然後這個語句將它重置到繫結值的時候的那個狀態。
Return: SQLITE_BUSY,SQLITE_DONE,SQLITE_ROW。
SQLITE_BUSY: 暫時無法執行操作.
SQLITE_DONE: 操作執行完畢.
SQLITE_ROW: 執行完畢並且有返回(執行select語句時);需要對查詢結果進行處理,SQLITE3提供sqlite3_column_*系列函式.
1.5 sqlite3_exec
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
該函式用來執行多條以“;”分隔的 SQL 語句。封裝了 sqlite3_prepare(), sqlte3_step() 和 sqlite3_finalize() 函式。
First: 資料庫連線控制程式碼。
Second: 將要被編譯的SQL語句。
Third: 回撥函式,若該函式非空,則每次SQL語法的結果都會呼叫該函式,若為空,則將被忽略。
Forth: 回撥函式的第一個引數。
Fifth: 儲存錯誤資訊,可為NULL;
Return: 返回非零,該函式立即中斷查詢,並不再執行後續的SQL語句和回撥函式;返回SQLITE_ABORT結束執行。
int callback(void *, int argc, char **argv, char **azColName);
First: 為sqlite3_exec中的第四個引數,即你所傳遞的引數。
Second: 執行SQL語法所產生的列元素個數。
Third: 執行SQL語法所產生的列元素列表,argv[i]代表第i個元素。
Forth: 執行SQL語法每行中各列的列名。
1.6 sqlite3_bind_XXX
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
給引數繫結值。
First: 指向一個被編譯的語句控制程式碼,它可被sqlite3_step執行。執行錯誤或者輸入的zSql為空字元,*ppStmt為NULL,用sqlite3_finalize來釋放它。
Second: SQL引數(每列元素)的索引,從0開始.
Third: 字串值。
Forth: 字串長度。
Fifth: 一個函式指標,SQLITE3執行完操作後回撥此函式,通常用於釋放字串佔用的記憶體。此引數有兩個常數,SQLITE_STATIC告訴sqlite3_bind_text函式字串為常量,可以放心使用;而SQLITE_TRANSIENT會使得sqlite3_bind_text函式對字串做一份拷貝。
1.7 sqlite3_column_XXX
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
這類函式從sqlite3_step()返回的結果集中提取某一列。
First: 指向一個被編譯的語句控制程式碼,它可被sqlite3_step執行。執行錯誤或者輸入的zSql為空字元,*ppStmt為NULL,用sqlite3_finalize來釋放它。
Second: SQL引數(每列元素)的索引,從1開始.
2、示例
2.1 開啟資料庫
#include <sqlite3.h>
#include <stdio.h>
int main(void)
{
sqlite3 *db;
sqlite3_stmt *res;
int rc = sqlite3_open("lab.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
sqlite3_close(db);
printf ("Succeed to open the database!
");
return 0;
}
$ gcc -o open open.c -lsqlite3
$ ./open
Succeed to open the database!
2.2 建立目標資料表
#include <sqlite3.h>
#include <stdio.h>
int main ()
{
sqlite3 *db;
sqlite3_stmt *res;
int rc = sqlite3_open("lab.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *SQL = "CREATE TABLE IF NOT EXISTS testtable (ID INTEGER PRIMARY KEY, name TEXT, gender TEXT, age REAL, value REAL)";
if(sqlite3_prepare_v2(db, SQL, -1, &res, 0)) {
printf("Failed to create table!
");
if (res)
sqlite3_finalize(res);
sqlite3_close(db);
return 1;
}
if (sqlite3_step(res) != SQLITE_DONE) {
sqlite3_finalize(res);
sqlite3_close(db);
return 1;
}
sqlite3_finalize(res);
printf ("Succeed to create testtable now.
");
sqlite3_close(db);
return 0;
}
$ gcc -o create create.c -lsqlite3
$ ./create
Succeed to create testtable now!
2.3 資料表操作
#include <sqlite3.h>
#include <stdio.h>
int main ()
{
sqlite3 *db;
sqlite3_stmt *res;
int rc = sqlite3_open("lab.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *err_msg = 0;
/* 想實現哪項功能,就將註釋去掉 */
//char *SQL = "INSERT INTO testtable VALUES(NULL, `xiao`, `male`, 100, 0.1)";//向資料表中插入一條資料
//char *SQL = "DELETE FROM testtable WHERE gender = males AND age = 26";//刪除資料表中的多條資料
//char *SQL = "DELETE FROM testtable";//刪除資料表中所有資料
//char *SQL = "UPDATE testtable SET gender = female,age=30 WHERE ID = 1";//更新資料表中的多條資料
//char *SQL = "DROP TABLE IF EXISTS testtable";//刪除資料表
int rc2 = sqlite3_exec(db, SQL, 0, 0, &err_msg);
if(rc2 != SQLITE_OK) {
fprintf(stderr, "Failed to drop table
");
fprintf(stderr, "SQL error: %s
", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return;
}
sqlite3_close(db);
printf ("Succeed!
");
return 0;
}
$ gcc -o table table.c -lsqlite3
$ ./table
Succeed!
2.4 批量插入資料
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
int main ()
{
sqlite3 *db;
int rc = sqlite3_open("lab.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
/* 手動開啟事物 */
sqlite3_stmt* stmtb = NULL;
const char* beginSQL = "BEGIN TRANSACTION";
if (sqlite3_prepare_v2(db,beginSQL,strlen(beginSQL),&stmtb,NULL) != SQLITE_OK) {
if (stmtb)
sqlite3_finalize(stmtb);
sqlite3_close(db);
return 1;
}
if (sqlite3_step(stmtb) != SQLITE_DONE) {
sqlite3_finalize(stmtb);
sqlite3_close(db);
return 1;
}
sqlite3_finalize(stmtb);
/*****************************/
char *err_msg = 0;
char *sql = "INSERT INTO testtable VALUES(NULL, ?, ?, ?, ?)";
sqlite3_stmt *stmt = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
char *name = "xiao";
char *m = "male";
char *f = "female";
for (int i = 1; i <= 10; i++) {
sqlite3_bind_null (stmt, 0);
sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
if(i % 2 == 0)
sqlite3_bind_text(stmt, 2, m, -1, SQLITE_TRANSIENT);
else
sqlite3_bind_text(stmt, 2, f, -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, i + 24);
double fl = i * 9.9;
sqlite3_bind_double(stmt, 4, fl);
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
sqlite3_reset(stmt);
}
sqlite3_finalize(stmt);
/* 手動關閉事物 */
sqlite3_stmt* stmtc = NULL;
const char *commitSQL = "COMMIT TRANSACTION";
if (sqlite3_prepare_v2(db,commitSQL,strlen(commitSQL),&stmtc,NULL) != SQLITE_OK) {
if (stmtc)
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
if (sqlite3_step(stmtc) != SQLITE_DONE) {
sqlite3_finalize(stmtc);
sqlite3_close(db);
return 1;
}
sqlite3_finalize(stmtc);
/*********************************/
sqlite3_close(db);
return 0;
}
$ gcc -o insert_datas insert_datas.c -lsqlite3
$ ./insert_data
$ sqlite3 lab.db
sqlite3> SELECT * FROM testtable;
1|xiao|female|25.0|9.9
2|xiao|male|26.0|19.8
3|xiao|female|27.0|29.7
4|xiao|male|28.0|39.6
5|xiao|female|29.0|49.5
6|xiao|male|30.0|59.4
7|xiao|female|31.0|69.3
8|xiao|male|32.0|79.2
9|xiao|female|33.0|89.1
10|xiao|male|34.0|99.0
2.5 顯示資料表的資料(non call_back)
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
int main ()
{
sqlite3 *db;
int rc = sqlite3_open("lab.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
const char *sql = "SELECT * FROM testtable";
sqlite3_stmt *stmt = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
int fieldcout = sqlite3_column_count (stmt);
do {
int r = sqlite3_step(stmt);
if (r == SQLITE_ROW) {
int i;
for (i = 0; i < fieldcout; ++i) {
int vtype = sqlite3_column_type(stmt, i);
if (vtype == SQLITE_INTEGER) {
int v = sqlite3_column_int(stmt, i);
printf ("%d
", v);
} else if (vtype == SQLITE_FLOAT) {
double v = sqlite3_column_double(stmt, i);
printf ("%f
", v);
} else if (vtype == SQLITE_TEXT) {
const char *v = (const char *)sqlite3_column_text(stmt, i);
printf("%s
", v);
} else if (vtype == SQLITE_NULL) {
printf ("NULL
");
}
}
} else if (r == SQLITE_DONE) {
printf ("Select finish.
");
break;
} else {
printf ("Failed to select.
");
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
} while (1);
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
$ gcc -o select select.c -lsqlite3
$ ./select
1
xiao
female
25.000000
9.900000
2
xiao
male
26.000000
19.800000
...
...
...
10
xiao
male
34.000000
99.000000
2.6 call_back
#include <sqlite3.h>
#include <stdio.h>
int callback(void *, int, char **, char **);
int main(void) {
sqlite3 *db;
char *err_msg = 0;
int rc = sqlite3_open("lab.db", &db);
if(rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s
", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *sql = "PRAGMA table_info(testtable)";
rc = sqlite3_exec(db, sql, callback, 0, &err_msg);
if(rc != SQLITE_OK) {
fprintf(stderr, "Failed to select data
");
fprintf(stderr, "SQL error: %s
", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return 1;
}
sqlite3_close(db);
return 0;
}
int callback(void *NotUsed, int argc, char **argv, char **azColName) {
NotUsed = 0;
int i;
for (i = 0; i < argc; i++) {
printf ("%s = %s
", azColName[i], argv[i]?argv[i]:"NULL");
}
printf("
");
return 0;
}
$ gcc -o callback callback.c -lsqlite3
$ ./callback
cid = 0
name = ID
type = INTEGER
notnull = 0
dflt_value = NULL
pk = 1
...
...
...
cid = 4
name = value
type = REAL
notnull = 0
dflt_value = NULL
pk = 0