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;
}
- 輸出結果
欄目導航
上一篇:SQLite學習筆記(九)– 視圖的定義與刪除(C++實現)
下一篇:無
智能推薦
ORACLE學習筆記-ORACLE基本概念
ORACLE學習筆記-ORACLE基本概念 數據庫名 數據庫名是存儲在控制文件中的名稱,它代表的是數據庫,也就是數據庫包含的所有的物理文件的總稱。數據庫名即下圖的全局數據庫名,實例名即下圖的SID 查詢數據庫名稱SQL: 查詢數據庫當前實例名: **實例名 ** 用于響應某個數據庫操作的數據庫管理系統的名稱。實例名是由初始化參數文件的參數instance_name決定的。如果這個參數不被指定(即i...
Java 學習筆記——基本概念
Java 學習筆記——基本概念 類與對象 primitive 主要數據類型與引用 方法操作實例變量 萬物皆對象,真正的java程序只會讓對象與對象交互,交互即相互調用方法 類與對象 類是對象的藍圖,它會告訴虛擬機如何創建某種類型的對象。根據某類創建出來的額對象都會有自己的實例變量。 main()函數:在對象之外,用來(1)測試真正的類;(2)啟動你的java應用程序 pri...
ElasticSearch學習筆記【一】基本概念
基本概念 cluster:代表一個集群,集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對于集群內部來說的。es的一個概念就是去中心化,字面上理解就是無中心節點,這是對于集群外部來說的,因為從外部來看es集群,在邏輯上是個整體,你與任何一個節點的通信和與整個es集群通信是等價的。 shards:代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
猜你喜歡
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...