SQLite C++操作类

为了方便SQLite的使用,封装了一个SQLite的C++类,同时支持ANSI 和UNICODE编码。代码如下:
 
头文件(SQLite.h)
[cpp] view plaincopy
/********************************************************************
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)
[cpp] view plaincopy
/********************************************************************
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,pwStr,-1,NULL,NULL);
if (len <= 0)
{
return NULL;
}
char *pStr = new char[len];
WideCharToMultiByte(CP_UTF8,pStr,len,NULL);
return pStr;
}
 
const wchar_t* Utf8ToWchar(const char *pStr)
{
if (pStr == NULL)
{
return NULL;
}
 
int len = MultiByteToWideChar(CP_UTF8,0);
if (len <= 0)
{
return NULL;
}
wchar_t *pwStr = new wchar_t[len];
MultiByteToWideChar(CP_UTF8,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,&stmt,NULL) != SQLITE_OK)
#else
if(sqlite3_prepare_v2(m_db,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,&errmsg) != SQLITE_OK)
{
delete[] szSql;
return FALSE;
}
delete[] szSql;
#else
if(sqlite3_exec(m_db,&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,NULL) != SQLITE_OK)
#endif
{
return FALSE;
}
return SQLiteDataReader(stmt);
}
 
// 开始事务
BOOL SQLite::BeginTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"BEGIN TRANSACTION;",&errmsg) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
// 提交事务
BOOL SQLite::CommitTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"COMMIT TRANSACTION;;",&errmsg) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
// 回滚事务
BOOL SQLite::RollbackTransaction()
{
char * errmsg = NULL;
if(sqlite3_exec(m_db,"ROLLBACK TRANSACTION;",&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,&m_pStmt,NULL) != SQLITE_OK)
#else
if(sqlite3_prepare_v2(m_pSqlite->m_db,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,SQLITE_TRANSIENT) != SQLITE_OK)
#else
if(sqlite3_bind_text(m_pStmt,SQLITE_TRANSIENT) != SQLITE_OK)
#endif
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index,const int nValue)
{
if(sqlite3_bind_int(m_pStmt,nValue) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index,const double dValue)
{
if(sqlite3_bind_double(m_pStmt,dValue) != SQLITE_OK)
{
return FALSE;
}
return TRUE;
}
 
BOOL SQLiteCommand::BindParam(int index,const unsigned char* blobBuf,int nLen)
{
if(sqlite3_bind_blob(m_pStmt,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类操作数据库的基本代码如下:
[cpp] view plaincopy
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,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,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};
// 绑定第三个参数(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,_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...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


SQLite架构简单,又有Json计算能力,有时会承担Json文件/RESTful的计算功能,但SQLite不能直接解析Json文件/RESTful,需要用Java代码硬写,或借助第三方类库,最后再拼成insert语句插入数据表,代码非常繁琐,这里就不展示了。参考前面的代码可知,入库的过程比较麻烦,不能只用SQL,还要借助Java或命令行。SPL是现代的数据计算语言,属于简化的面向对象的语言风格,有对象的概念,可以用点号访问属性并进行多步骤计算,但没有继承重载这些内容,不算彻底的面向对象语言。...
使用Python操作内置数据库SQLite以及MySQL数据库。
破解微信数据库密码,用python导出微信聊天记录
(Unity)SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。本教程将告诉您如何使用 SQLite 编程,并让你迅速上手。.................................
安卓开发,利用SQLite实现登陆注册功能
相比大多数数据库而言,具有等优势,广泛应用于、等领域。
有时候,一个项目只有一个数据库,比如只有SQLite,或者MySQL数据库,那么我们只需要使用一个固定的数据库即可。但是一个项目如果写好了,有多个用户使用,但是多个用户使用不同的数据库,这个时候,我们就需要把软件设计成可以连接多个数据库的模式,用什么数据库,就配置什么数据库即可。4.Users实体类,这个实体类要和数据库一样的,形成一一对应的关系。11.Sqlite数据库,需要在代码里面创建数据库,建立表,再建立数据。8.我们开启MySQL数据库,然后进行调试,看程序的结果。2.安装SqlSugar。
基于Android的背单词软件,功能强大完整。
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。说白了就是使用起来轻便简单,
Android的简单购物车案例
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库...
Qt设计较为美观好看的登录注册界面(包含SQLite数据库以及TCP通信的应用)
SQLite是用C语言开发的跨平台小型数据库,可嵌入其他开发语言,也可在单机执行。SPL是用Java开发的跨平台的数据计算语言,可嵌入Java,可在单机执行,可以数据计算服务的形式被远程调用。两者的代码都是解释执行的。...
新建库.openDATA_BASE;新建表createtableLIST_NAME(DATA);语法:NAME关键字...<用逗号分割>删除表droptableNAME;查看表.schema查看表信息新建数据insertintoLIST_NAMEvalues();语法:CLASS,PARAMETER...,CLASS是类别,PARAMETER是参数<用逗号分割新建的
importsqlite3classDemo01:def__init__(self):self.conn=sqlite3.connect("sql_demo_001.db")self.cursor1=self.conn.cursor()self.cursor1.execute("select*fromtable_001wherename=?andid=?",('ssss&#0
 在客户端配置文件<configuration>节点下,添加:<connectionStrings>      <add name="localdb" connectionString="Data Source=config/local.db;Version=3;UseUTF16Encoding=True;" providerName="System.Data.SQLite.SQLiteFactory"/&g
提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁。下面举个例子:连接1:BEGIN(UNLOCKED)连接1:SELECT...(SHARED)连接1:INSERT...(RESERVED)连接2:BEGIN(UNLOCKED)连接2:SELECT...(SHARED)连接1:COMMIT(PENDING,尝试获取EXCLUSIVE锁,但还有SHARED锁未释放,返回SQLITE_BUSY)连接2:INSERT...
SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。在使用SQLite前,我们先要搞清楚几个概念:表
设计思想————首先要确定有几个页面、和每个页面的大致布局由于是入门,我也是学习了不是很长的时间,所以项目比较low。。。。第一个页面,也就是打开APP的首页面:今天这个博客,先实现添加功能!:首先对主界面进行布局:其中activity_main.xml的代码为<?xmlversion="1.0"encoding="