1. 程式人生 > >SQLite學習筆記(十)-- 事務基本概念和程式碼實現(C++實現)

SQLite學習筆記(十)-- 事務基本概念和程式碼實現(C++實現)

1.事務基本概念

  • 什麼是事務?
    事務是使用者定義的一些列資料操作,這些操作是一個完整的不可分的工作單元。一個事務要麼全部執行,要麼全部不執行。
  • 檢視案例
    例如銀行的轉賬操作,張三向李四轉賬1000元。該事務包含以下兩個操作:
    1.張三賬戶上扣除1000元;
    2.李四賬戶上增加1000元。
    這兩個操作就構成一個事務操作。兩個操作要麼全部執行,要麼全部不執行。只執行任意一個,都會導致賬戶金額的混亂。
    該事務的具體程式碼見下文。
  • SQLite事務執行流程
    1.以begin語句開啟一個事務;
    2.依次執行事務中的所有操作,並檢查其是否執行成功;
    3.如果所有操作全部成功,則執行commit語句;否則執行rollback語句。

2.程式碼例項

  • 程式碼說明
    本例主要展示用事務模式來執行轉賬操作。
  • 測試平臺
    1.開發語言:C++
    2.開發工具:VS2015
    3.作業系統:Win7 X64
  • 測試資料說明
    測試表為Account表,其結構如下:
    這裡寫圖片描述
    測試表的內容如下:
    這裡寫圖片描述

  • 具體程式碼

#include <iostream>
#include <Windows.h>
using namespace std;

//sqlite3標頭檔案
#include "sqlite3.h"
//sqlite3庫檔案
#pragma comment(lib,"sqlite3.lib")

//函式功能:將utf8字元轉gb2312字元
//引數: const char* utf8[IN] -- UTF8字元 //返回值: char* -- gb2312字元 char* U2G(const char* utf8) { int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); wchar_t* wstr = new wchar_t[len + 1]; memset(wstr, 0, len + 1); MultiByteToWideChar(CP_UTF8, 0
, utf8, -1, wstr, len); len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); char* str = new char[len + 1]; memset(str, 0, len + 1); WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL); if (wstr) delete[] wstr; return str; } //unicode字元轉utf8 //函式功能:將gb2312字元轉換為utf8字元 //引數: const char* gb2312[IN] -- gb2312字元 //返回值: char* -- UTF8字元 char* G2U(const char* gb2312) { int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0); wchar_t* wstr = new wchar_t[len + 1]; memset(wstr, 0, len + 1); MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len); len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); char* str = new char[len + 1]; memset(str, 0, len + 1); WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL); if (wstr) delete[] wstr; return str; } //函式功能:事務操作函式 //引數: sqlite3 *db[IN] --資料庫操作控制代碼 //返回值: bool --函式執行成功,則返回true;否則返回false bool BeginTranction(sqlite3 *db) { int iAmount = 1000; //假設轉賬金額為1000 bool bRet = false; int rc; char sql[3000]; char *pErrMsg = 0; //開啟事務 rc = sqlite3_exec(db, "begin;", NULL, 0, &pErrMsg); if (rc != SQLITE_OK) { cout << "操作發生失敗,失敗原因:" << pErrMsg << endl;; sqlite3_free(pErrMsg); bRet = false; } else { cout << "資料庫事務開啟成功" << endl; bool successFlag = false; //進行轉賬操作 sprintf_s(sql, "UPDATE Account Set BALANCE=BALANCE-%d WHERE NAME='%s';", iAmount, G2U("張三")); rc = sqlite3_exec(db, sql, NULL, 0, &pErrMsg); if (rc != SQLITE_OK) { cout << "轉賬操作發生失敗,失敗原因:" << pErrMsg << endl;; sqlite3_free(pErrMsg); bRet = false; } else { cout << "張三轉出" << iAmount << "操作成功" << endl; sprintf_s(sql, "UPDATE Account Set BALANCE = BALANCE + %d WHERE NAME = '%s'; ", iAmount, G2U("李四")); rc = sqlite3_exec(db, sql, NULL, 0, &pErrMsg); if (rc != SQLITE_OK) { cout << "轉賬操作發生失敗,失敗原因:" << pErrMsg << endl;; sqlite3_free(pErrMsg); bRet = false; } else { cout << "李四收入" << iAmount << "操作成功" << endl; } successFlag = true; } if (successFlag) { //操作全部成功情況下,提交事務 sqlite3_exec(db, "commit;", NULL, 0, 0); cout << "資料庫完成事務操作" << endl; bRet = false; } else { //操作沒有全部成功,需要回滾 sqlite3_exec(db, "rollback;", NULL, 0, 0); cout << "事務操作失敗,回滾" << endl; bRet = true; } } return bRet; } //函式功能:使用查詢表方式查詢賬戶資料 //引數: sqlite3 *db[IN] --資料庫操作控制代碼 //返回值: bool --函式執行成功,則返回true;否則返回false bool Select_QueryTable(sqlite3 *db) { bool bRet = false; int rc; char sql[3000]; char *pErrMsg = 0; sprintf_s(sql, "SELECT * FROM 'Account';"); string m_SqlCommand(sql); char** pResult; int nRow; int nCol; int nResult = sqlite3_get_table(db, m_SqlCommand.c_str(), &pResult, &nRow, &nCol, &pErrMsg); if (nResult != SQLITE_OK) { //注意,執行失敗,需要清理錯誤碼的記憶體空間 sqlite3_free(pErrMsg); return false; } int nIndex = nCol; int cnt = 0; for (int i = 0; i<nRow; i++) { for (int j = 0; j<nCol; j++) { cout << U2G(pResult[j]) << ":" << U2G(pResult[nIndex]) << " "; ++nIndex; } cout << endl; } sqlite3_free_table(pResult); return true; } int main() { sqlite3 *pDataBase = NULL; //開啟資料庫 //如果路徑不含中文,可以不用轉碼。不過保險起見,建議全部轉碼。 int iRet = sqlite3_open(G2U("E:\\sqlite資料庫\\testSQLite.db"), &pDataBase); if (iRet) { cout << "資料庫開啟失敗,失敗原因:" << sqlite3_errmsg(pDataBase) << endl; } else { cout << "資料庫開啟成功!" << endl; cout << "原始資料:" << endl; //以查詢表方式查詢資料 Select_QueryTable(pDataBase); //執行事務,張三轉賬給李四1000元 BeginTranction(pDataBase); //轉賬結果 cout << endl << "轉賬後資料資料:" << endl; Select_QueryTable(pDataBase); //關閉資料庫 iRet= sqlite3_close(pDataBase); if (0 == iRet) { cout << "資料庫關閉成功!" << endl; } } getchar(); return 0; }
  • 輸出結果
    這裡寫圖片描述