SQLite C++操作类
为了方便SQLite的使用,封装了一个SQLite的C++类,同时支持ANSI 和UNICODE编码。代码如下:
 
头文件(SQLite.h)
/********************************************************************
filename: SQLite.h
created: 2012-11-05
author: firehood
 
purpose: SQLite数据库操作类
*********************************************************************/
#pragma once
#include <windows.h>
#include "..\SQLite\sqlite3.h"
#pragma comment(lib,"SQLite.lib")
 
typedef BOOL (WINAPI *QueryCallback) (void *para, int n_column, char **column_value, char **column_name);
 
typedef enum _SQLITE_DATATYPE
{
SQLITE_DATATYPE_INTEGER = SQLITE_INTEGER,
SQLITE_DATATYPE_FLOAT = SQLITE_FLOAT,
SQLITE_DATATYPE_TEXT = SQLITE_TEXT,
SQLITE_DATATYPE_BLOB = SQLITE_BLOB,
SQLITE_DATATYPE_NULL= SQLITE_NULL,
}SQLITE_DATATYPE;
 
class SQLite;
 
class SQLiteDataReader
{
public:
SQLiteDataReader(sqlite3_stmt *pStmt);
~SQLiteDataReader();
public:
// 读取一行数据
BOOL Read();
// 关闭Reader,读取结束后调用
void Close();
// 总的列数
int ColumnCount(void);
// 获取某列的名称
LPCTSTR GetName(int nCol);
// 获取某列的数据类型
SQLITE_DATATYPE GetDataType(int nCol);
// 获取某列的值(字符串)
LPCTSTR GetStringValue(int nCol);
// 获取某列的值(整形)
int GetIntValue(int nCol);
// 获取某列的值(长整形)
long GetInt64Value(int nCol);
// 获取某列的值(浮点形)
double GetFloatValue(int nCol);
// 获取某列的值(二进制数据)
const BYTE* GetBlobValue(int nCol, int &nLen);
private:
sqlite3_stmt *m_pStmt;
};
 
class SQLiteCommand
{
public:
SQLiteCommand(SQLite* pSqlite);
SQLiteCommand(SQLite* pSqlite,LPCTSTR lpSql);
~SQLiteCommand();
public:
// 设置命令
BOOL SetCommandText(LPCTSTR lpSql);
// 绑定参数(index为要绑定参数的序号,从1开始)
BOOL BindParam(int index, LPCTSTR szValue);
BOOL BindParam(int index, const int nValue);
BOOL BindParam(int index, const double dValue);
BOOL BindParam(int index, const unsigned char* blobValue, int nLen);
// 执行命令
BOOL Excute();
// 清除命令(命令不再使用时需调用该接口清除)
void Clear();
private:
SQLite *m_pSqlite;
sqlite3_stmt *m_pStmt;
};
 
class SQLite
{
public:
SQLite(void);
~SQLite(void);
public:
// 打开数据库
BOOL Open(LPCTSTR lpDbFlie);
// 关闭数据库
void Close();
 
// 执行非查询操作(更新或删除)
BOOL ExcuteNonQuery(LPCTSTR lpSql);
BOOL ExcuteNonQuery(SQLiteCommand* pCmd);
 
// 查询
SQLiteDataReader ExcuteQuery(LPCTSTR lpSql);
// 查询(回调方式)
BOOL ExcuteQuery(LPCTSTR lpSql,QueryCallback pCallBack);
 
// 开始事务
BOOL BeginTransaction();
// 提交事务
BOOL CommitTransaction();
// 回滚事务
BOOL RollbackTransaction();
 
// 获取上一条错误信息
LPCTSTR GetLastErrorMsg();
public:
friend class SQLiteCommand;
private:
sqlite3 *m_db;
};
 
 
源文件(SQLite.cpp)
/********************************************************************
filename: SQLite.cpp
created: 2012-11-05
author: firehood
 
purpose: SQLite数据库操作类
*********************************************************************/
#include "SQLite.h"
 
const char* WcharToUtf8(const wchar_t *pwStr)
{
if (pwStr == NULL)
{
return NULL;
}
 
int len = WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, NULL, 0, NULL, NULL);
if (len <= 0)
{
return NULL;
}
char *pStr = new char[len];
WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, pStr, len, NULL, NULL);
return pStr;
}
 
const wchar_t* Utf8ToWchar(const char *pStr)
{
if (pStr == NULL)
{
return NULL;
}
 
int len = MultiByteToWideChar(CP_UTF8, 0, pStr, -1, NULL, 0);
if (len <= 0)
{
return NULL;
}
wchar_t *pwStr = new wchar_t[len];
MultiByteToWideChar(CP_UTF8, 0, pStr, -1, pwStr, len);
return pwStr;
}
 
SQLite::SQLite(void):
m_db(NULL)
{
}
 
SQLite::~SQLite(void)
{
Close();
}
 
BOOL SQLite::Open(LPCTSTR lpDbFlie)
{
if(lpDbFlie == NULL)
{
return FALSE;
}
#ifdef UNICODE
if(sqlite3_open16(lpDbFlie,&m_db) != SQLITE_OK)
#else
if(sqlite3_open(lpDbFlie,&m_db) != SQLITE_OK)
#endif
{
return FALSE;
}
return TRUE;
}
 
void SQLite::Close()
{
if(m_db)
{
sqlite3_close(m_db);
m_db = NULL;
}
}
 
BOOL SQLite::ExcuteNonQuery(LPCTSTR lpSql)
{
if(lpSql == NULL)
{
return FALSE;
}
sqlite3_stmt* stmt;
#ifdef UNICODE
if(sqlite3_prepare16_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK)
#else
if(sqlite3_prepare_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK)
#endif
{
return FALSE;
}
sqlite3_step(stmt);
 
return (sqlite3_finalize(stmt) == SQLITE_OK) ? TRUE : FALSE ;
}
 
BOOL SQLite::ExcuteNonQuery(SQLiteCommand* pCmd)
{
if(pCmd == NULL)
{
return FALSE;
}
return pCmd->Excute();
}
 
// 查询(回调方式)
BOOL SQLite::ExcuteQuery(LPCTSTR lpSql,QueryCallback pCallBack)
{
if(lpSql == NULL || pCallBack == NULL)
{
return FALSE;
}
char *errmsg = NULL;
#ifdef UNICODE
const char *szSql = WcharToUtf8(lpSql);
if(sqlite3_exec(m_db, szSql, pCallBack, NULL, &errmsg) != SQLITE_OK)
{
delete[] szSql;
return FALSE;
}
delete[] szSql;
#else
if(sqlite3_exec(m_db, lpSql, pCallBack, NULL, &errmsg) != SQLITE_OK)
{
return FALSE;
}
#endif
return TRUE;
}
 
// 查询
SQLiteDataReader SQLite::ExcuteQuery(LPCTSTR lpSql)
{
if(lpSql == NULL)
{
return FALSE;
}
sqlite3_stmt* stmt;
#ifdef UNICODE
if(sqlite3_prepare16_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK)
#else
if(sqlite3_prepare_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK)
#endif
{
return FALSE;
}
return SQLiteDataReader(stmt);
}
 
// 开始事务
BOOL SQLite::BeginTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"BEGIN TRANSACTION;",NULL,NULL,&errmsg) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
// 提交事务
BOOL SQLite::CommitTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"COMMIT TRANSACTION;;",NULL,NULL,&errmsg) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
// 回滚事务
BOOL SQLite::RollbackTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"ROLLBACK TRANSACTION;",NULL,NULL,&errmsg) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
// 获取上一条错误信息
LPCTSTR SQLite::GetLastErrorMsg()
{
#ifdef UNICODE
return (LPCTSTR)sqlite3_errmsg16(m_db);
#else
return sqlite3_errmsg(m_db);
#endif
}
 
 
 
SQLiteDataReader::SQLiteDataReader(sqlite3_stmt *pStmt):
m_pStmt(pStmt)
{
 
}
 
SQLiteDataReader::~SQLiteDataReader()
{
Close();
}
 
// 读取一行数据
BOOL SQLiteDataReader::Read()
{
if(m_pStmt == NULL)
{
return FALSE;
}
if(sqlite3_step(m_pStmt) != SQLITE_ROW)
{
return FALSE;
}
return TRUE;
}
 
// 关闭Reader,读取结束后调用
void SQLiteDataReader::Close()
{
if(m_pStmt)
{
sqlite3_finalize(m_pStmt);
m_pStmt = NULL;
}
}
 
// 总的列数
int SQLiteDataReader::ColumnCount(void)
{
return sqlite3_column_count(m_pStmt);
}
 
// 获取某列的名称
LPCTSTR SQLiteDataReader::GetName(int nCol)
{
#ifdef UNICODE
return (LPCTSTR)sqlite3_column_name16(m_pStmt, nCol);
#else
return (LPCTSTR)sqlite3_column_name(m_pStmt, nCol);
#endif
}
 
// 获取某列的数据类型
SQLITE_DATATYPE SQLiteDataReader::GetDataType(int nCol)
{
return (SQLITE_DATATYPE)sqlite3_column_type(m_pStmt, nCol);
}
 
// 获取某列的值(字符串)
LPCTSTR SQLiteDataReader::GetStringValue(int nCol)
{
#ifdef UNICODE
return (LPCTSTR)sqlite3_column_text16(m_pStmt, nCol);
#else
return (LPCTSTR)sqlite3_column_text(m_pStmt, nCol);
#endif
}
 
// 获取某列的值(整形)
int SQLiteDataReader::GetIntValue(int nCol)
{
return sqlite3_column_int(m_pStmt, nCol);
}
 
// 获取某列的值(长整形)
long SQLiteDataReader::GetInt64Value(int nCol)
{
return (long)sqlite3_column_int64(m_pStmt, nCol);
}
 
// 获取某列的值(浮点形)
double SQLiteDataReader::GetFloatValue(int nCol)
{
return sqlite3_column_double(m_pStmt, nCol);
}
 
// 获取某列的值(二进制数据)
const BYTE* SQLiteDataReader::GetBlobValue(int nCol, int &nLen)
{
nLen = sqlite3_column_bytes(m_pStmt, nCol);
return (const BYTE*)sqlite3_column_blob(m_pStmt, nCol);
}
 
SQLiteCommand::SQLiteCommand(SQLite* pSqlite):
m_pSqlite(pSqlite),
m_pStmt(NULL)
{
}
 
SQLiteCommand::SQLiteCommand(SQLite* pSqlite,LPCTSTR lpSql):
m_pSqlite(pSqlite),
m_pStmt(NULL)
{
SetCommandText(lpSql);
}
 
SQLiteCommand::~SQLiteCommand()
{
 
}
 
BOOL SQLiteCommand::SetCommandText(LPCTSTR lpSql)
{
#ifdef UNICODE
if(sqlite3_prepare16_v2(m_pSqlite->m_db, lpSql, -1, &m_pStmt, NULL) != SQLITE_OK)
#else
if(sqlite3_prepare_v2(m_pSqlite->m_db, lpSql, -1, &m_pStmt, NULL) != SQLITE_OK)
#endif
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index, LPCTSTR szValue)
{
#ifdef UNICODE
if(sqlite3_bind_text16(m_pStmt, index, szValue, -1, SQLITE_TRANSIENT) != SQLITE_OK)
#else
if(sqlite3_bind_text(m_pStmt, index, szValue,-1, SQLITE_TRANSIENT) != SQLITE_OK)
#endif
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index, const int nValue)
{
if(sqlite3_bind_int(m_pStmt, index, nValue) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index, const double dValue)
{
if(sqlite3_bind_double(m_pStmt, index, dValue) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index, const unsigned char* blobBuf, int nLen)
{
if(sqlite3_bind_blob(m_pStmt, index, blobBuf,nLen,NULL) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::Excute()
{
sqlite3_step(m_pStmt);
 
return (sqlite3_reset(m_pStmt) == SQLITE_OK) ? TRUE : FALSE ;
}
 
void SQLiteCommand::Clear()
{
if(m_pStmt)
{
sqlite3_finalize(m_pStmt);
}
}
 
使用方法
通过SQLite类操作数据库的基本代码如下:
void SqliteOperate()
{
TCHAR *szDbPath = _T("Book.db");
 
::DeleteFile(szDbPath);
 
SQLite sqlite;
 
// 打开或创建数据库
//******************************************************
if(!sqlite.Open(szDbPath))
{
_tprintf(_T("%s\n"),sqlite.GetLastErrorMsg());
return;
}
//******************************************************
 
// 创建数据库表
//******************************************************
TCHAR sql[512] = {0};
_stprintf(sql,_T("%s"),
_T("CREATE TABLE [Book] (")
_T("[id] INTEGER NOT NULL PRIMARY KEY, ")
_T("[name] NVARCHAR(20), ")
_T("[author] NVARCHAR(20), ")
_T("[catagory_id] INTEGER REFERENCES [Category]([id]), ")
_T("[abstruct] NVARCHAR(100) ,")
_T("[path] NVARCHAR(50), ")
_T("[image] BLOB);")
_T("CREATE INDEX [Book_id] ON [Book] ([id]);")
);
if(!sqlite.ExcuteNonQuery(sql))
{
printf("Create database table failed...\n");
}
//******************************************************
 
// 插入数据【普通方式】
DWORD dwBeginTick = GetTickCount();
//******************************************************
// 当一次性插入多条记录时候,采用事务的方式,提高效率
sqlite.BeginTransaction();
// 批量插入数据
for(int i=0;i<1000;i++)
{
memset(sql,0,sizeof(sql));
_stprintf(sql,_T("insert into Book(name,author,catagory_id) values('红高粱%d','莫言',1)"),i);
if(!sqlite.ExcuteNonQuery(sql))
{
_tprintf(_T("%s\n"),sqlite.GetLastErrorMsg());
break;
}
}
// 提交事务
sqlite.CommitTransaction();
printf("Insert Data Take %dMS...\n",GetTickCount()-dwBeginTick);
//******************************************************
 
 
// 插入数据【通过参数绑定的方式,提交批量数据时,比上面的普通模式效率更高(提高约45%),同时可支持插入二进制数据】
dwBeginTick = GetTickCount();
//******************************************************
// 当一次性插入多条记录时候,采用事务的方式,提高效率
sqlite.BeginTransaction();
memset(sql,0,sizeof(sql));
_stprintf(sql,_T("insert into Book(name,author,catagory_id,image) values(?,'韩寒',?,?)"));
SQLiteCommand cmd(&sqlite,sql);
// 批量插入数据
for(int i=0;i<1000;i++)
{
TCHAR strValue[16] = {0};
_stprintf(strValue,_T("他的国%d"),i);
// 绑定第一个参数(name字段值)
cmd.BindParam(1,strValue);
// 绑定第二个参数(catagory_id字段值)
cmd.BindParam(2,20);
BYTE imageBuf[] = {0xff,0xff,0xff,0xff};
// 绑定第三个参数(image字段值,二进制数据)
cmd.BindParam(3,imageBuf,sizeof(imageBuf));
if(!sqlite.ExcuteNonQuery(&cmd))
{
_tprintf(_T("%s\n"),sqlite.GetLastErrorMsg());
break;
}
}
// 清空cmd
cmd.Clear();
// 提交事务
sqlite.CommitTransaction();
printf("Insert Data Take %dMS...\n",GetTickCount()-dwBeginTick);
//******************************************************
 
// 查询
dwBeginTick = GetTickCount();
//******************************************************
memset(sql,0,sizeof(sql));
_stprintf(sql,_T("%s"),_T("select * from Book where name = '他的国345'"));
 
SQLiteDataReader Reader = sqlite.ExcuteQuery(sql);
 
int index = 0;
int len = 0;
while(Reader.Read())
{
_tprintf( _T("***************【第%d条记录】***************\n"),++index);
_tprintf( _T("字段名:%s 字段值:%d\n"),Reader.GetName(0),Reader.GetIntValue(0));
_tprintf( _T("字段名:%s 字段值:%s\n"),Reader.GetName(1),Reader.GetStringValue(1));
_tprintf( _T("字段名:%s 字段值:%s\n"),Reader.GetName(2),Reader.GetStringValue(2));
_tprintf( _T("字段名:%s 字段值:%d\n"),Reader.GetName(3),Reader.GetIntValue(3));
_tprintf( _T("字段名:%s 字段值:%s\n"),Reader.GetName(4),Reader.GetStringValue(4));
// 读取图片二进制文件
const BYTE *ImageBuf = Reader.GetBlobValue(6,len);
_tprintf( _T("*******************************************\n"));
}
Reader.Close();
printf("Query Take %dMS...\n",GetTickCount()-dwBeginTick);
//******************************************************
 
// 关闭数据库
sqlite.Close();
}
 
运行结果
Insert Data Take 645MS...
Insert Data Take 229MS...
***************【第1条记录】***************
字段名:id 字段值:1346
字段名:name 字段值:他的国345
字段名:author 字段值:韩寒
字段名:catagory_id 字段值:20
字段名:abstruct 字段值:(null)
*******************************************
Query Take 63MS...
 

SQLite C++操作种的更多相关文章

  1. Django 模型层之多表操作

    一.创建模型 实例: 作者表: 拥有字段:姓名(name),性别(sex),该表与书籍表之间为多对多的关系 作者详情表: 拥有字段:地址(addr),手机号(phone),该表与作者表之间为一对一的关 ...

  2. 实战:基于 Spring 的应用配置如何迁移至阿里云应用配置管理 ACM

    最近遇到一些开发者朋友,准备将原有的Java Spring的应用配置迁移到 阿里云应用配置管理 ACM 中.迁移过程中,遇到不少有趣的问题.本文将通过一个简单的样例来还原迁移过程中遇到的问题和相关解决 ...

  3. java Class的Long id初始化 为0的问题android数据库操做出现的 android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed

    java的class中的Long类型变量调用默认的 构造函数new后会被初始化为0. 这句话大家可能感觉这么低级的事情还用你说? 我想说的是这个会产生的一个应用场景 和 避免方法 场景:db插入时候p ...

  4. SQLite剖析之事务处理技术

    前言 事务处理是DBMS中最关键的技术,对SQLite也一样,它涉及到并发控制,以及故障恢复等等.在数据库中使用事务可以保证数据的统一和完整性,同时也可以提高效率.假设需要在一张表内一次插入20个人的 ...

  5. [Nhibernate]sqlite数据库基本使用

    目录 写在前面 操作步骤 总结 写在前面 昨天有朋友问我在nhibernate中如何使用sqlite数据库,当时实在忙的不可开交,下周要去山西出差,实在没空,按我的说法使用sqlite跟使用sqlse ...

  6. sqlite原子提交原理

    英文地址 文章参考 简介 支持事务的数据库系统如sqlite的一个重要特性是原子提交(atomic commit).也就是在一个事务中进行的对数据库的写操作要么全部执行,要么全部不执行.看起来像是对数 ...

  7. android: SQLite 数据库的最佳实践

    6.5.1    使用事务 前面我们已经知道,SQLite 数据库是支持事务的,事务的特性可以保证让某一系列的操 作要么全部完成,要么一个都不会完成.那么在什么情况下才需要使用事务呢?想象以下场 景, ...

  8. android: SQLite创建数据库

    SQLite 是一款轻量级的关系型数据库,它的运算速度非常快, 占用资源很少,通常只需要几百 K 的内存就足够了,因而特别适合在移动设备上使用.SQLite 不仅支持标准的 SQL 语法,还遵循了数据 ...

  9. SQLite在多线程环境下的应用

    文一 SQLite的FAQ里面已经专门说明,先贴出来.供以后像我目前的入门者学习. (7) 多个应用程序或者同一个应用程序的多个例程能同时存取同一个数据库文件吗? 多进程可以同时打开同一个数据库,也可 ...

随机推荐

  1. 在centos6.5 上安装最新版mysql

    在mysql上如果直接安装mysql安装的不是5.6版本以上.下面记录怎么解决安装最新版mysql5.6以上. 1.查看本机都安装了mysql什么版本:rpm -qa | grep mysql,默认是 ...

  2. scikit-learn 应用

    首先是sklearn的官网:http://scikit-learn.org/stable/ 在官网网址上可以看到很多的demo,下边这张是一张非常有用的流程图,在这个流程图中,可以根据数据集的特征,选 ...

  3. HDU 3308 线段树求区间最长连续上升子序列长度

    题意:两种操作,Q L R查询L - R 的最长连续上升子序列长度,U pos val 单点修改值 #include <bits/stdc++.h> #define N 100005 us ...

  4. c_数据结构_二叉树的遍历实现

    #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define OVERFLOW -2 #d ...

  5. python的异常捕捉

    你可能会说既然有万能异常Exception,那么我直接用上面的这种形式就好了,其他异常可以忽略 你说的没错,但是应该分两种情况去看 1.如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一 ...

  6. postgresql使用pg_dump和pg_restore 实现跨服务器的数据库迁移或备份

    因为业务需求,需要将服务器上的postgre多个数据库的数据整个库得迁移到另一个postgre数据库上. 一般表较少时,会使用postgre 的copy to 和 copy from 命令就能完成表的 ...

  7. Erlang学习记录:app demo

    目录结构 │ Emakefile │ make.bat │ start.bat ├─config │ config.config │ server.app ├─ebin │ wulin_app.bea ...

  8. Perl 基础语法

    Perl 基础语法 Perl借用了C.sed.awk.shell脚本以及很多其他编程语言的特性,语法与这些语言有些类似,也有自己的特点. Perl 程序有声明与语句组成,程序自上而下执行,包含了循环, ...

  9. 0921CSP-S模拟测试赛后总结

    倒数第一祭. 感觉T3数据范围50可以qj一下.于是押了T3. 然后两个小时调我4.1k的bfs.最后调出来了发现策略错了.十分绝望. T120分吊住了.十分难过.倒数第一了.还是实力不行. 不应该押 ...

  10. NOI2001 炮兵阵地 洛谷2704

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...