Linux下的c/c++開發之操作Sqlite3數據庫

libsqlite3-dev 介紹(Linux 下的 SQLite3 C/C++ 開發包)

libsqlite3-dev 是一個開發包,在 Linux 環境下為使用 SQLite3 C API 進行開發的 C/C++ 程序員提供頭文件(如 sqlite3.h)和靜態庫/動態庫的鏈接信息(如 libsqlite3.so)。

它是 SQLite3 數據庫的開發接口版本,不提供命令行工具,而是用于編譯和構建程序時使用。

libsqlite3-dev 包含的內容:

類型路徑描述
頭文件/usr/include/sqlite3.h主頭文件,聲明所有 SQLite3 C API 函數,如 sqlite3_opensqlite3_execsqlite3_close
/usr/include/sqlite3ext.hSQLite3 插件擴展接口(用于實現用戶自定義函數等)
動態庫/usr/lib/x86_64-linux-gnu/libsqlite3.so動態鏈接庫,編譯時鏈接使用,運行時自動加載
靜態庫/usr/lib/x86_64-linux-gnu/libsqlite3.a靜態鏈接庫(可選,靜態鏈接使用)
頭文件路徑/usr/include/所有頭文件通常放在此處,包含時使用 <sqlite3.h>

libsqlite3-dev的安裝

sudo apt update
sudo apt install libsqlite3-dev

安裝成功后的簡單示例:

test_sqlite3.cpp

#include <sqlite3.h>
#include <iostream>int main() {sqlite3* db = nullptr;int rc = sqlite3_open("test.db", &db);if(rc != SQLITE_OK) {std::cerr << "打開數據庫失敗: " << sqlite3_errmsg(db) << std::endl;if (db) {sqlite3_close(db);  // 即使打開失敗也可能需要關閉 db}return 1;}std::cout << "SQLite3 數據庫打開成功!" << std::endl;sqlite3_close(db);return 0;
}

編譯:

gcc test_sqlite3.c -o test_sqlite3 -lsqlite3

正常情況下運行后輸出:

SQLite3 數據庫打開成功!

<sqlite3.h> 介紹

<sqlite3.h> 是 SQLite3 的主頭文件,提供了完整的 SQLite3 C 接口函數集,你可以通過它來完成:

  • 打開或創建數據庫文件(sqlite3_open

  • 執行 SQL(sqlite3_exec

  • 查詢數據(sqlite3_prepare_v2 + sqlite3_step + sqlite3_column_xxx

  • 錯誤處理(sqlite3_errmsg

  • 事務管理(BEGIN, COMMIT, ROLLBACK

  • 內存管理、自定義函數、BLOB 操作等高級特性

它是你在 Linux 下用 C/C++ 訪問 SQLite3 數據庫的入口。

<sqlite3.h>中的結構體

常用結構體簡介

結構體名類型作用描述使用場景舉例
sqlite3數據庫連接對象表示與 SQLite 數據庫的連接,所有操作都依賴它sqlite3_open, sqlite3_close 用于打開和關閉數據庫
sqlite3_stmt預處理語句句柄表示一條 SQL 語句的預編譯句柄(如 SELECT、INSERT、UPDATE)sqlite3_prepare_v2, sqlite3_step 用于執行預處理語句
sqlite3_value列值表示 SQLite 查詢結果中的單一列數據的類型(可以是整數、文本、BLOB、NULL)使用 sqlite3_column_* 函數從查詢結果中提取數據
sqlite3_row行數據表示數據庫查詢結果中的一行數據,存儲在一個 sqlite3_value 結構體中遍歷查詢結果時,使用 sqlite3_column_* 獲取每一列
sqlite3_vfs虛擬文件系統用于管理 SQLite 的文件 I/O 操作,定義 SQLite 如何讀寫數據文件可用于自定義虛擬文件系統或定制文件 I/O
sqlite3_context執行上下文用于執行回調時保存狀態的結構體,通常在用戶定義的函數中使用在自定義 SQLite 函數時使用,保存用戶的上下文數據

?sqlite3

sqlite3 結構體是 SQLite 數據庫的主要句柄,表示一個數據庫連接,管理數據庫的生命周期和執行查詢的操作。

typedef struct sqlite3 sqlite3;

示例:

sqlite3 *db;
int rc = sqlite3_open("test.db", &db);
if (rc) {fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
} else {printf("Opened database successfully\n");
}

sqlite3_value

sqlite3_value 結構體表示 SQLite 中的一個值(例如列值、函數參數)。它包含了該值的類型和實際的數據。

typedef struct sqlite3_value sqlite3_value;

示例:

sqlite3_value *value;
value = sqlite3_column_value(stmt, 0);
if (sqlite3_value_type(value) == SQLITE_INTEGER) {printf("Value is integer: %lld\n", sqlite3_value_int64(value));
}

sqlite3_row

sqlite3_row 結構體表示查詢結果中的一行數據。SQLite 使用它來存儲查詢返回的每一行的字段數據。

typedef struct sqlite3_row sqlite3_row;

示例:

sqlite3_row *row;
while ((row = sqlite3_fetch_row(stmt)) != NULL) {const char *name = sqlite3_column_text(row, 0);int age = sqlite3_column_int(row, 1);printf("Name: %s, Age: %d\n", name, age);
}

sqlite3_stmt

sqlite3_stmt 結構體表示一個預處理語句。它包含了 SQL 查詢的編譯結果,并提供了執行該查詢的接口。

typedef struct sqlite3_stmt sqlite3_stmt;

示例:

sqlite3_stmt *stmt;
const char *sql = "SELECT id, name FROM users WHERE age > ?";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);

<sqlite3.h>中常用的方法

1. 初始化與連接管理

sqlite3_open

用于打開一個 SQLite 數據庫連接(若數據庫文件不存在則嘗試創建),是使用 SQLite 的入口函數之一。

int sqlite3_open(const char *filename, sqlite3 **ppDb);

參數:

  • filename:數據庫文件名。如果傳入 ":memory:",則創建一個內存數據庫;如果傳入 "",創建一個臨時數據庫。

  • ppDb:傳入一個 sqlite3 指針的地址,成功后返回已打開的數據庫連接指針。

返回值:

  • 成功:返回 SQLITE_OK

  • 失敗:返回其他錯誤碼,例如 SQLITE_CANTOPEN。錯誤信息可通過 sqlite3_errmsg() 獲取。

?

sqlite3_open_v2

sqlite3_open 的增強版本,支持更多控制選項(如只讀、創建標志、自定義虛擬文件系統等)。

int sqlite3_open_v2(const char *filename,sqlite3 **ppDb,int flags,const char *zVfs
);

參數:

  • filename:數據庫文件路徑,規則同 sqlite3_open

  • ppDb:傳出參數,返回數據庫連接句柄。

  • flags:控制數據庫打開行為。常用值包括:

    • SQLITE_OPEN_READONLY:只讀模式打開。

    • SQLITE_OPEN_READWRITE:可讀寫(數據庫必須存在)。

    • SQLITE_OPEN_CREATE:如果不存在則創建數據庫。

    • 可組合使用,如 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE

  • zVfs:VFS 模塊名稱,傳 NULL 使用默認模塊。

返回值:

int sqlite3_close(sqlite3*);
  • 成功:返回 SQLITE_OK

  • 失敗:返回錯誤碼,例如 SQLITE_CANTOPENSQLITE_NOTADB 等。

sqlite3_close

關閉一個已經打開的 SQLite 數據庫連接,并釋放相關資源。此函數要求數據庫中沒有未完成的語句句柄(sqlite3_stmt)或未釋放的內存,否則關閉會失敗。

int sqlite3_close(sqlite3*);

參數:

  • sqlite3*:由 sqlite3_opensqlite3_open_v2 打開的數據庫連接句柄。

返回值:

  • 成功:返回 SQLITE_OK

  • 失敗:返回 SQLITE_BUSY(表示還有未釋放的資源,如未 finalize 的語句)。

sqlite3_close_v2

sqlite3_close 類似,也是關閉數據庫連接。但它允許有未清理的語句存在,數據庫會被標記為“延遲關閉”,直到最后一個資源被釋放后自動關閉。

int sqlite3_close_v2(sqlite3*);

sqlite3_errmsg

返回最近一次 SQLite 操作失敗的錯誤信息(字符串形式),用于調試和日志記錄。

const char *sqlite3_errmsg(sqlite3*);

參數:

  • sqlite3*:數據庫連接句柄。

返回值:

  • 返回一個字符串,表示上一次出錯時的詳細錯誤信息。這個字符串是由 SQLite 管理的,不需要手動釋放。

注意事項:

  • 如果是線程安全模式,不要跨線程使用該字符串。

  • 錯誤信息只對上一次失敗的調用有效,之后任何成功調用都會覆蓋它。

sqlite3_errcode

返回最近一次數據庫操作的錯誤代碼(整數形式),用于程序內判斷錯誤類型。

int sqlite3_errcode(sqlite3*);

參數:

  • sqlite3*:數據庫連接句柄。

返回值:

  • 返回錯誤代碼,如:

    • SQLITE_OK:無錯誤。

    • SQLITE_BUSY:資源忙。

    • SQLITE_ERROR:SQL 錯誤或數據庫缺陷。

    • SQLITE_IOERR:磁盤 I/O 錯誤。

    • SQLITE_NOMEM:內存不足。

    • 等等,詳見官方文檔錯誤碼列表。

sqlite3_extended_errcode

返回更詳細的錯誤碼,錯誤信息比 sqlite3_errcode 更細致,例如區分不同類型的 SQLITE_IOERR_*

int sqlite3_extended_errcode(sqlite3*);

參數:

  • sqlite3*:數據庫連接句柄。

返回值:

  • 返回擴展錯誤代碼,例如:

    • SQLITE_IOERR_READ

    • SQLITE_IOERR_WRITE

    • SQLITE_CONSTRAINT_UNIQUE

示例:

#include <sqlite3.h>
#include <iostream>void open_with_sqlite3_open(const char* filename) {sqlite3* db = nullptr;std::cout << "[sqlite3_open] 嘗試打開數據庫: " << filename << "\n";int rc = sqlite3_open(filename, &db);if (rc != SQLITE_OK) {std::cerr << "打開失敗\n";std::cerr << "  錯誤碼: " << sqlite3_errcode(db) << "\n";std::cerr << "  擴展錯誤碼: " << sqlite3_extended_errcode(db) << "\n";std::cerr << "  錯誤信息: " << sqlite3_errmsg(db) << "\n";} else {std::cout << "打開成功\n";}if (db) {sqlite3_close(db);std::cout << "[sqlite3_close] 已關閉數據庫連接\n";}
}void open_with_sqlite3_open_v2(const char* filename) {sqlite3* db = nullptr;std::cout << "[sqlite3_open_v2] 嘗試以讀寫模式打開數據庫: " << filename << "\n";int rc = sqlite3_open_v2(filename,&db,SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,nullptr // 使用默認 VFS);if (rc != SQLITE_OK) {std::cerr << "打開失敗\n";std::cerr << "  錯誤碼: " << sqlite3_errcode(db) << "\n";std::cerr << "  擴展錯誤碼: " << sqlite3_extended_errcode(db) << "\n";std::cerr << "  錯誤信息: " << sqlite3_errmsg(db) << "\n";} else {std::cout << "打開成功\n";}if (db) {sqlite3_close_v2(db);std::cout << "[sqlite3_close_v2] 已關閉數據庫連接(異步可安全延后)\n";}
}int main() {std::cout << "===== 使用 sqlite3_open =====\n";open_with_sqlite3_open("example_open.db");std::cout << "\n===== 使用 sqlite3_open_v2 =====\n";open_with_sqlite3_open_v2("example_open_v2.db");return 0;
}

2. 執行 SQL(直接執行)

sqlite3_exec

sqlite3_exec() 是 SQLite 提供的一個簡化接口,用于直接執行一條或多條 SQL 語句。適合執行不需要處理結果集的語句,如 CREATE TABLEINSERTUPDATEDELETE 等。

sqlite3_exec() 的執行過程中,我們可以通過回調函數來處理查詢結果,sqlite3_exec() 直接返回所有結果并逐行傳遞給回調函數。

int sqlite3_exec(sqlite3 *db,                // 數據庫連接句柄const char *sql,            // SQL 語句int (*callback)(void*,int,char**,char**), // 回調函數(可為 NULL)void *arg,                  // 傳給回調函數的參數(可為 NULL)char **errmsg               // 出錯信息(執行失敗時會分配內存)
);

參數

  • db:打開的數據庫連接句柄(由 sqlite3_open() 獲得)。

  • sql:要執行的一條或多條 SQL 語句,語句之間用分號分隔。

  • callback:每當 SQL 查詢返回一行結果時調用的函數。如果沒有回調函數,可以傳 NULL

  • arg:傳遞給回調函數的上下文數據,可以是任何自定義的數據。可以傳 NULL

  • errmsg:如果非 NULL,執行失敗時將設置指向錯誤信息字符串的指針。調用者需要在完成后調用 sqlite3_free() 釋放此內存。

返回值

  • SQLITE_OK:表示執行成功。

  • 其他錯誤碼:執行失敗,具體錯誤信息可以通過 errmsg 獲得。


示例:

#include <sqlite3.h>
#include <iostream>int callback(void* NotUsed, int argc, char** argv, char** azColName) {for (int i = 0; i < argc; i++) {std::cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << "\n";}std::cout << "------\n";return 0;
}int main() {sqlite3* db = nullptr;char* errMsg = nullptr;// 打開數據庫if (sqlite3_open("test_exec.db", &db) != SQLITE_OK) {std::cerr << "無法打開數據庫: " << sqlite3_errmsg(db) << "\n";return 1;}// 創建表并插入數據const char* sql = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT);""INSERT INTO users(name) VALUES('Alice');""INSERT INTO users(name) VALUES('Bob');""SELECT * FROM users;";if (sqlite3_exec(db, sql, callback, nullptr, &errMsg) != SQLITE_OK) {std::cerr << "SQL 執行錯誤: " << errMsg << "\n";sqlite3_free(errMsg); // 釋放錯誤信息}// 關閉數據庫sqlite3_close(db);return 0;
}

3. 預處理語句與結果集處理

SQLite 不像 MySQL 那樣返回一個“結果集對象(MYSQL_RES)”,它通過“預處理語句對象”sqlite3_stmt* 來遍歷每一行返回結果。以下是預處理語句和處理查詢結果時的主要函數。

sqlite3_prepare_v2

將 SQL 語句編譯成可執行的預處理語句。

int sqlite3_prepare_v2(sqlite3 *db,              // 數據庫連接句柄const char *sql,          // 要編譯的 SQL 語句int nByte,                // SQL 語句的長度,如果是字符串以外的字符,可以傳 -1sqlite3_stmt **ppStmt,    // 輸出的 sqlite3_stmt 句柄const char **pzTail       // 指向 SQL 語句中未被解析的部分,通常可以為 NULL
);

參數:

  • db:數據庫連接句柄。

  • sql:待編譯的 SQL 語句。

  • nByte:SQL 語句的長度,若是字符串,傳 -1。

  • ppStmt:返回預處理語句的 sqlite3_stmt 句柄。

  • pzTail:指向 SQL 語句未解析部分的指針,通常可以為 NULL

返回值:

  • SQLITE_OK:表示成功。

  • 其他錯誤碼:表示失敗。

sqlite3_bind_* 系列函數

sqlite3_bind_* 系列函數用于將動態的值綁定到 SQL 語句中的占位符參數,以便執行時能夠傳遞實際數據。

常用函數

  • sqlite3_bind_int:綁定整數參數。

  • sqlite3_bind_text:綁定文本參數。

  • sqlite3_bind_double:綁定浮動參數。

  • sqlite3_bind_blob:綁定二進制數據。

  • sqlite3_bind_null:綁定 NULL 值。

int sqlite3_bind_int(sqlite3_stmt *pStmt, int iParam, int value);
int sqlite3_bind_text(sqlite3_stmt *pStmt, int iParam, const char *value, int n, void (*destructor)(void*));
int sqlite3_bind_double(sqlite3_stmt *pStmt, int iParam, double value);
int sqlite3_bind_blob(sqlite3_stmt *pStmt, int iParam, const void *value, int n, void (*destructor)(void*));
int sqlite3_bind_null(sqlite3_stmt *pStmt, int iParam);
  • 參數

    • pStmt:預處理語句句柄。

    • iParam:參數的索引,從 1 開始。

    • value:要綁定的值。

    • n:值的字節數,適用于文本、二進制數據。

    • destructor:用于清理 value 的回調函數,通常用于 TEXTBLOB 數據類型。

  • 返回值

    • SQLITE_OK:表示成功。

    • 其他錯誤碼:表示失敗。

sqlite3_clear_bindings

用于清除通過 sqlite3_bind_* 系列函數綁定到 SQL 語句中的所有參數值,但不會重置語句的編譯狀態(即不會清除結果或重置游標)。適用于想重用已準備好的 SQL 語句但重新綁定新參數的場景。

int sqlite3_clear_bindings(sqlite3_stmt *pStmt);

參數:

  • pStmt:已準備好的 SQL 語句對象(sqlite3_prepare_v2 的輸出)。

返回值:

  • 返回 SQLITE_OK 表示綁定清除成功。

  • 傳入非法的 pStmt 時可能返回其他錯誤碼。

sqlite3_reset

用于重置一個已執行的預處理語句(sqlite3_stmt*),將其狀態清空,以便再次綁定參數并重新執行。該函數不會清除綁定的參數值(除非配合 sqlite3_clear_bindings() 使用),而是將語句返回到 sqlite3_step() 執行前的初始狀態。

int sqlite3_reset(sqlite3_stmt *pStmt);

參數:

  • pStmt:類型為 sqlite3_stmt*,表示需要被重置的預處理語句句柄。這個句柄通常是通過 sqlite3_prepare_v2() 創建的。

返回值:

  • 返回 SQLITE_OK 表示重置成功,語句已回到初始狀態,下一次可以重新綁定參數并執行。

  • 如果返回的是非 SQLITE_OK 的其他錯誤碼,則是該語句上一次執行 sqlite3_step() 時的返回碼,這通常可用于調試或進一步的錯誤處理。

sqlite3_step

執行預處理語句并處理每一行的結果。

int sqlite3_step(sqlite3_stmt *pStmt);

參數:

  • pStmt:預處理語句句柄,由 sqlite3_prepare_v2 返回。

返回值:

  • SQLITE_ROW:有一行數據可返回。

  • SQLITE_DONE:查詢完成,所有行已處理完。

  • 其他錯誤碼:表示執行過程中出錯。

每次調用 sqlite3_step,都會推進 sqlite3_stmt 句柄至下一行數據。每當 sqlite3_step 返回 SQLITE_ROW 時,表示當前行的查詢結果可以通過 sqlite3_column_* 系列函數獲取。

sqlite3_column_* 系列函數

從當前行的結果中提取列的數據。

常用函數

  • sqlite3_column_text:返回文本類型的列數據。

  • sqlite3_column_int:返回整數類型的列數據。

  • sqlite3_column_double:返回浮動類型的列數據。

  • sqlite3_column_blob:返回二進制數據。

  • sqlite3_column_bytes:返回列數據的字節數。

const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int col);
int sqlite3_column_int(sqlite3_stmt *pStmt, int col);
double sqlite3_column_double(sqlite3_stmt *pStmt, int col);
const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int col);
int sqlite3_column_bytes(sqlite3_stmt *pStmt, int col);
  • 參數

    • pStmt:預處理語句句柄。

    • col:列的索引,從 0 開始。

  • 返回值

    • 對應的列數據,如文本、整數、浮動等。

sqlite3_finalize

釋放預處理語句占用的資源。

int sqlite3_finalize(sqlite3_stmt *pStmt);
  • 參數

    • pStmt:預處理語句句柄。

  • 返回值

    • SQLITE_OK:表示成功。

    • 其他錯誤碼:表示失敗。

使用 sqlite3_finalize 清理 sqlite3_stmt 占用的資源。即使查詢執行成功,釋放預處理語句也是必要的步驟。

示例:

#include <sqlite3.h>
#include <iostream>int main() {sqlite3 *db;sqlite3_stmt *stmt;// 打開數據庫if (sqlite3_open("test.db", &db) != SQLITE_OK) {std::cerr << "無法打開數據庫: " << sqlite3_errmsg(db) << "\n";return 1;}// 編譯 SQL 語句const char *sql = "SELECT id, name FROM users WHERE age > ?";if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {std::cerr << "無法編譯 SQL: " << sqlite3_errmsg(db) << "\n";sqlite3_close(db);return 1;}// 第一次綁定參數并執行查詢sqlite3_bind_int(stmt, 1, 30);  // 綁定 age > 30std::cout << "查詢 age > 30 的用戶:\n";while (sqlite3_step(stmt) == SQLITE_ROW) {int id = sqlite3_column_int(stmt, 0);const unsigned char *name = sqlite3_column_text(stmt, 1);std::cout << "ID: " << id << ", Name: " << name << std::endl;}// 清除綁定參數并重置語句sqlite3_clear_bindings(stmt);  // 清除參數綁定sqlite3_reset(stmt);           // 重置語句狀態,準備再次執行// 第二次綁定新參數并再次查詢sqlite3_bind_int(stmt, 1, 20);  // 綁定 age > 20std::cout << "\n查詢 age > 20 的用戶:\n";while (sqlite3_step(stmt) == SQLITE_ROW) {int id = sqlite3_column_int(stmt, 0);const unsigned char *name = sqlite3_column_text(stmt, 1);std::cout << "ID: " << id << ", Name: " << name << std::endl;}// 清理資源sqlite3_finalize(stmt);sqlite3_close(db);return 0;
}

4.狀態信息獲取

sqlite3_db_filename

該函數用于獲取當前數據庫連接所關聯的數據庫文件名。這對于調試、日志記錄或者獲取數據庫文件路徑非常有用。

const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);

參數

  • db:SQLite 數據庫連接句柄。

  • zDbName:數據庫名稱。如果是主數據庫,使用 "main";如果是附加數據庫,使用附加數據庫的名稱。

返回值

  • 返回指定數據庫(如主數據庫或附加數據庫)對應的文件名(路徑)。如果出錯,則返回 NULL

示例:


const char *filename = sqlite3_db_filename(db, "main");
if (filename) {std::cout << "主數據庫文件路徑: " << filename << "\n";
} else {std::cerr << "獲取文件名失敗\n";
}
sqlite3_db_status

該函數用于獲取有關數據庫的狀態信息,如內存使用情況、鎖狀態、緩存大小等。它為用戶提供了一個接口來監控數據庫的性能和資源使用。

int sqlite3_db_status(sqlite3 *db,        // 數據庫連接句柄int op,             // 狀態信息的類型(如內存使用,鎖狀態等)int *pCur,          // 當前狀態值int *pHiwater,      // 高水位值int reset           // 是否重置狀態
);

參數

  • db:SQLite 數據庫連接句柄。

  • op:要查詢的狀態類型。常見的狀態類型有:

    • SQLITE_DBSTATUS_LOOKASIDE_HIT:查看緩存命中的次數。

    • SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:查看緩存未命中的大小。

    • SQLITE_DBSTATUS_CACHE_USED:查看緩存當前使用的字節數。

    • SQLITE_DBSTATUS_MEMORY_USED:查看當前內存使用量。

    • 還有其他類型的狀態查詢,詳細請參考 SQLite 官方文檔。

  • pCur:返回當前的狀態值。

  • pHiwater:返回該狀態的最高水位(例如最大內存使用量)。

  • reset:如果設置為非零值,則會重置狀態統計數據(用于獲取從上次調用以來的變化)。

返回值

  • 返回 SQLITE_OK 表示成功。

  • 其他錯誤碼表示失敗。

示例:

int currentUsage = 0;
int highWaterMark = 0;
int rc = sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &currentUsage, &highWaterMark, 0);
if (rc == SQLITE_OK) {std::cout << "當前緩存使用字節數: " << currentUsage << "\n";std::cout << "緩存的最高使用字節數: " << highWaterMark << "\n";
} else {std::cerr << "獲取數據庫狀態失敗\n";
}

5.事務控制

SQLite 的事務控制相對簡化了一些,不像 MySQL 那樣提供專門函數(mysql_autocommit、mysql_commit、mysql_rollback等)。SQLite 更注重簡潔性和輕量性,因此很多事務控制操作都可以通過 sqlite3_exec 來完成,基本上是通過執行 SQL 語句來管理事務的開始、提交和回滾。

?示例:

#include <sqlite3.h>
#include <iostream>void execute_transaction(sqlite3 *db) {char *errMsg = nullptr;// 開始事務const char *beginSQL = "BEGIN TRANSACTION;";if (sqlite3_exec(db, beginSQL, nullptr, nullptr, &errMsg) != SQLITE_OK) {std::cerr << "開始事務失敗: " << errMsg << "\n";sqlite3_free(errMsg);return;}// 執行插入操作const char *insertSQL = "INSERT INTO users(name) VALUES('Alice');";if (sqlite3_exec(db, insertSQL, nullptr, nullptr, &errMsg) != SQLITE_OK) {std::cerr << "插入數據失敗: " << errMsg << "\n";sqlite3_free(errMsg);// 回滾事務const char *rollbackSQL = "ROLLBACK;";sqlite3_exec(db, rollbackSQL, nullptr, nullptr, &errMsg);return;}// 提交事務const char *commitSQL = "COMMIT;";if (sqlite3_exec(db, commitSQL, nullptr, nullptr, &errMsg) != SQLITE_OK) {std::cerr << "提交事務失敗: " << errMsg << "\n";sqlite3_free(errMsg);return;}std::cout << "事務執行成功\n";
}int main() {sqlite3 *db = nullptr;if (sqlite3_open("test_transaction.db", &db) != SQLITE_OK) {std::cerr << "無法打開數據庫: " << sqlite3_errmsg(db) << "\n";return 1;}// 執行事務execute_transaction(db);// 關閉數據庫sqlite3_close(db);return 0;
}

sqlite3.h中的錯誤碼和狀態碼

錯誤碼常量名稱含義描述
0SQLITE_OK操作成功
1SQLITE_ERROR通用錯誤
2SQLITE_INTERNALSQLite 內部邏輯錯誤
3SQLITE_PERM訪問權限被拒絕
4SQLITE_ABORT回調函數請求中止
5SQLITE_BUSY數據庫文件被鎖定
6SQLITE_LOCKED數據庫表被鎖定
7SQLITE_NOMEM內存分配失敗
8SQLITE_READONLY數據庫處于只讀模式,無法寫入
9SQLITE_INTERRUPT操作被 sqlite3_interrupt() 中斷
10SQLITE_IOERR磁盤 I/O 錯誤
11SQLITE_CORRUPT數據庫文件損壞
12SQLITE_NOTFOUND未找到指定的操作或對象
13SQLITE_FULL數據庫已滿,無法插入數據
14SQLITE_CANTOPEN無法打開數據庫文件
15SQLITE_PROTOCOL數據庫鎖協議錯誤
16SQLITE_EMPTY內部使用,僅供 SQLite 內部操作使用
17SQLITE_SCHEMA數據庫模式(schema)變化
18SQLITE_TOOBIG字符串或二進制數據超出大小限制
19SQLITE_CONSTRAINT由于約束沖突(如 UNIQUE 或 FOREIGN KEY)導致的中止
20SQLITE_MISMATCH數據類型不匹配
21SQLITE_MISUSE錯誤的庫調用,表示 SQLite 被錯誤地使用
22SQLITE_NOLFS使用了操作系統不支持的特性
23SQLITE_AUTH授權被拒絕
24SQLITE_FORMAT未使用,未定義的錯誤碼
25SQLITE_RANGEsqlite3_bind 的參數超出范圍
26SQLITE_NOTADB嘗試打開一個非數據庫文件
27SQLITE_NOTICE通知信息,通過 sqlite3_log() 返回
28SQLITE_WARNING警告信息,通過 sqlite3_log() 返回
100SQLITE_ROWsqlite3_step() 有一行數據可返回
101SQLITE_DONEsqlite3_step() 執行完成,所有行已處理完

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904608.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904608.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904608.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Prompt工程—文生圖】案例大全

目錄 一、人物繪圖 二、卡通頭像 三、風景圖 四、logo設計圖 五、動物形象圖 六、室內設計圖 七、動漫風格 八、二次元圖 九、日常場景圖 十、古風神化圖 十一、游戲場景圖 十二、電影大片質感 本文主要介紹了12種不同類型的文生圖技巧&#xff0c;通過加入不同的圖像…

GMRES算法處理多個右端項的Block與PseudoBlock變體

GMRES算法處理多個右端項的Block與PseudoBlock變體 Block與PseudoBlock GMRES簡介 在處理多個右端項的線性方程組時&#xff0c;Block GMRES和PseudoBlock GMRES是兩種常用的變體算法&#xff1a; Block GMRES&#xff1a;同時處理所有右端項&#xff0c;構建一個大的Krylov…

Ubuntu環境下如何管理系統中的用戶:創建用戶、刪除用戶、修改密碼、切換用戶、用戶組管理

管理用戶的操作需要root權限&#xff0c;在執行命令時需要加sudo&#xff0c;關于sudo命令可以看這篇&#xff1a;Linux_sudo命令的使用與機制 1、添加用戶 使用命令&#xff1a; adduser 用戶名&#xff0c;主要是按提示輸入密碼和用戶信息&#xff08;可直接回車使用默認配置…

開源BI選型及DataEase搭建

工具名稱 國家/社區技術棧核心功能國內適用性國外適用性推薦場景Apache Superset美國&#xff08;Apache&#xff09;Python/React可視化、SQL Lab、多數據源、插件擴展需自行漢化&#xff0c;社區支持較少生態完善&#xff0c;云原生支持好&#xff08;AWS/GCP&#xff09;中大…

云計算-容器云-部署jumpserver 版本1

部署jumpserver [root@jumpserver ~]# tar -zxvf jumpserver.tar.gz -C /opt/ [root@jumpserver ~]# ls /opt/ compose config docker docker.service images jumpserver-repo static.env將默認Yum源移至其他目錄,創建本地Yum源文件,命令及文件內容如下: [root@jumpserver…

利用Elixir中的原子特性 + 錯誤消息泄露 -- Atom Bomb

題目信息: This new atom bomb early warning system is quite strange… 題目使用 elixir 語言 一開始,我們會訪問 /page.html <!DOCTYPE html> <!-- 設定文檔語言為英語 --> <html lang"en"> <head><!-- 設定字符編碼為UTF-8 --><…

Spring MVC設計與實現

DispatcherServlet的初始化與請求處理流程 初始化階段 Servlet 生命周期觸發&#xff1a;當 Web 容器&#xff08;如 Tomcat&#xff09;啟動時&#xff0c;根據注解/配置&#xff0c;DispatcherServlet 的 init() 方法被調用。 初始化 WebApplicationContext 根 WebApplicat…

64.微服務保姆教程 (七) RocketMQ--分布式消息中間件

RocketMQ–分布式消息中間件 一、MQ 1、什么是MQ MQ(Message Queue)消息隊列,是基礎數據結構中“先進先出”的一種數據結構。指把要傳輸的數據(消息)放在隊列中,用隊列機制來實現消息傳遞——生產者產生消息并把消息放入隊列,然后由消費者去處理。消費者可以到指定隊…

java算法的核心思想及考察的解題思路

一、Java算法的核心思想 1. 分而治之 (Divide and Conquer) 將大問題分解為小問題&#xff0c;遞歸解決小問題后合并結果 典型應用&#xff1a;歸并排序、快速排序、二分查找 2. 動態規劃 (Dynamic Programming) 將問題分解為重疊子問題&#xff0c;存儲子問題的解避免重復…

linux查java進程CPU高的原因

問題&#xff1a;linux查java進程CPU高的原因 解決&#xff1a;用jdk帶的工具分析 被查的java最好也使用jdk啟動 systemctl啟動的注意要去掉PrivateTmptrue /opt/jdk1.8.0_441/bin/jps -l top -Hp 8156 printf "%x" 8533 /opt/jdk1.8.0_441/bin/jstack 8156 |…

體育培訓的實驗室管理痛點 質檢LIMS如何重構體育檢測價值鏈

在競技體育與全民健身并行的時代背景下&#xff0c;體育培訓機構正面臨雙重挑戰&#xff1a;既要通過科學訓練提升學員競技水平&#xff0c;又需嚴格把控運動安全風險。作為實驗室數字化管理的核心工具&#xff0c;質檢LIMS系統憑借其標準化流程管控與智能化數據分析能力&#…

linux下MySql的安裝與配置

一鍵三聯&#xff0c;把mysql的安裝與配置也寫了&#xff0c;供各位參考。 --------------------------------------MySql的安裝與配置-------------------------------------- 1 將下載的 壓縮包解壓到指定目錄 tar -zxvf mysql-5.7.26-linux-glibc2.12-x86_64.tar.gz 卸載…

數據庫原理與應用實驗二 題目七

利用sql建立教材數據庫,并定義以下基本表: 學生(學號,年齡,性別,系名) 教材(編號,書名,出版社編號,價格) 訂購(學號,書號,數量) 出版社(編號,名稱,地址) 1定義主碼、外碼、和價格、數量的取值范圍。 2 在三個表中輸入若干記錄,注意如果輸入違反完整…

什么是 HSQLDB?

大家好&#xff0c;這里是架構資源棧&#xff01;點擊上方關注&#xff0c;添加“星標”&#xff0c;一起學習大廠前沿架構&#xff01; Java開發人員學習Java數據庫連接&#xff08;JDBC&#xff09;的最簡單方法是試驗HyperSQL數據庫&#xff08;又名HSQLDB&#xff09;。 …

shell腳本--2

1、實時監控cpu、內存的shell腳本 #!/bin/bash# 獲取當前時間 DATE$(date "%Y-%m-%d %H:%M:%S")# 獲取CPU使用情況 CPU_USAGE$(top -b -n1 | grep "Cpu(s)" | awk {print $2 $4})# 獲取內存使用情況 MEMORY_USAGE$(free | grep Mem | awk {print $3/$2 *…

性能比拼: HTTP/2 vs. HTTP/3

本內容是對知名性能評測博主 Anton Putra HTTP/2 vs. HTTP/3 performance benchmark 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準 在本內容中&#xff0c;我們將比較 HTTP/2 和 HTTP/3 協議。 我們將使用 Terraform 和 Ansible 在 Google Cloud Platform (GCP) …

【Vue】組件自定義事件 TodoList 自定義事件數據傳輸

目錄 一、綁定 二、解綁 組件自定義事件總結 TodoList案例對數據傳輸事件的修改 總結不易~ 本章節對我有很大收獲&#xff0c; 希望對你也是&#xff01;&#xff01;&#xff01; 本章節素材已上傳Gitee&#xff1a;yihaohhh/我愛Vue - Gitee.com 前面我們學習的clikc、…

Windows遠程連接MySQL報錯,本地navicat能連接MySQL

一、報錯 telnet 119.87.111.79 3306??“無法打開到主機的連接。在端口 3306: 連接失敗”?? 表明無法通過 TCP 協議連接到目標服務器的 3306 端口。 二、目的 &#xff08;1&#xff09;??Telnet 測試的目的?? Telnet 僅用于測試 ??TCP 端口是否開放??&#xff…

電池管理系統BMS三級架構——BMU、BCU和BAU詳解

儲能電站的電池管理系統&#xff08;BMS&#xff09;通常采用三級架構&#xff1a;從控&#xff08;BMU&#xff09;、主控&#xff08;BCU&#xff09;、總控&#xff08;BAU&#xff09;。這種分層設計實現了電池模組、簇、堆的分級管理和控制&#xff0c;確保系統運行的安全…

C++ 基礎復習

基礎復習 1.const引用為什么能引用臨時對象2.內聯函數的額外作用3. nullptr 1.const引用為什么能引用臨時對象 臨時對象&#xff08;Temporary Object&#xff09;是在表達式求值過程中隱式創建的對象&#xff0c;例如&#xff1a; 函數返回非引用類型的值 類型轉換&#xff0…