C++封装SQLite实例<三>
前一篇博客中介绍的是怎样依据sqlite3_get_table()函数来获取一张表的内容,就是一股脑的把表中的内容所有存储起来放在一个一维数组中,这其中的规则已经介绍过了。接下来讲的是怎样依据一个SQL查询语句来挑选出合乎选择条件的记录,被挑选出的记录事先是不知道的。你不知道这个查询的结果中有几行更不知道每一行中详细的记录值是什么,所以没办法用给定行值和列值的方式来获取数据,所有之前的用数组存储表的方式即可不通了。想要灵活的管理一个查询返回的结果这就会复杂多了,用到的SQLite原生函数也非常多。
这个CppSQLite3Query类中有四个字段,各自是
sqlite3 *mpDB;
sqlite3_stmt *mpStmt;
bool mbEof; //因为查询的结果须要一行一行的訪问,所以设置一个bool值来表示是否达到最后一行的结尾
int mnCols; //表示这个查询结果的列数,行数是无法得知的
第一个參数:查询要连接的数据库
第二个參数:
** CAPI3REF: SQL Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement.
** This object is variously known as a "prepared statement" or a
** "compiled SQL statement" or simply as a "statement".
**
** The life of a statement object goes something like this:
**
** <ol>
** <li> Create the object using [sqlite3_prepare_v2()] or a related
** function.
** <li> Bind values to [host parameters] using the sqlite3_bind_*()
** interfaces.
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
** <li> Reset the statement using [sqlite3_reset()] then go back
** to step 2. Do this zero or more times.
** <li> Destroy the object using [sqlite3_finalize()].
** </ol>
是一个SQL语句对象,或是说一条原生的SQL查询语句select * from XXX;经过SQLite处理后就生成了一个sqlite3_stmt对象。以后就能够不用原生的语句来做查询,就直接使用这个sqlite3_stmt*就能够查询了,当查询结束后,要将sqlite3_stmt*指针对象释放掉。
释放函数sqlite3_finalize()和sqlite3_free();函数功能类似,仅仅只是后者是释放sqlite3*对象的,而前者是释放sqlite3_stmt*对象的。
函数原型 SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
函数说明:
/*
** CAPI3REF: Destroy A Prepared Statement Object
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
** [extended error code].
**
** ^The sqlite3_finalize(S) routine can be called at any point during
** the life cycle of [prepared statement] S:
** before statement S is ever evaluated, after
** one or more calls to [sqlite3_reset()], or after any call
** to [sqlite3_step()] regardless of whether or not the statement has
** completed execution.
**
** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
**
** The application must finalize every [prepared statement] in order to avoid
** resource leaks. It is a grievous error for the application to try to use
** a prepared statement after it has been finalized. Any use of a prepared
** statement after it has been finalized can result in undefined and
** undesirable behavior such as segfaults and heap corruption.
*/
用来初始化mnCols字段的函数是:
SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
函数说明:
/*
** CAPI3REF: Number Of Columns In A Result Set
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
** statement that does not return data (for example an [UPDATE]).
**
** See also: [sqlite3_data_count()]
*/
在依据列索引值获取当前列的列名用到的函数:
函数原型:SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
在推断数据是否为空的时候要用到检測数据类型的函数:
函数原型:SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
这个函数返回的是一个整型,当中不同的数值代表不同的已定义好的宏,以下是各种类型:
#define SQLITE_INTEGER 1
#define SQLITE_FLOAT 2
#define SQLITE_BLOB 4
#define SQLITE_NULL 5
#ifdef SQLITE_TEXT
# undef SQLITE_TEXT
#else
# define SQLITE_TEXT 3
#endif
#define SQLITE3_TEXT 3
另一种查询数据类型的函数
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
他返回的直接是类型名称。
在获取各种不同类型数据的时候用到各种函数,他们返回不同的数据类型的值:
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
上面的一些函数可能没有出如今这个封装的C++类中。
以下直接贴代码:
class CppSQLite3Query
{
private:
sqlite3 *mpDB;
sqlite3_stmt *mpStmt;
bool mbEof;
int mnCols; void CheckStmt();
public:
CppSQLite3Query();
CppSQLite3Query(sqlite3 *pdb, sqlite3_stmt *pStmt, bool bEof);
CppSQLite3Query(const CppSQLite3Query &rQuery);
CppSQLite3Query& operator= (const CppSQLite3Query &rQuery);
~CppSQLite3Query(); int FieldNums(); int FieldIndex(const char* szField);
const char* FieldName(int nField); int FieldDataType(int nField);
const char* FieldDeclType(int nField); const char* FieldValue(int nField);
const char* FieldValue(const char *szField); bool FieldIsNull(int nField);
bool FieldIsNull(const char *szField); bool GetIntValue(int nField, int &rDest);
bool GetIntValue(const char *szField, int &rDest); bool GetFloatValue(int nField, double &rDest);
bool GetFloatValue(const char *szField, double &rDest); bool GetStringValue(int nField, char *&rDest);
bool GetStringValue(const char *szField, char *&rDest); bool Eof(); void NextRow(); void Finalize();
};
CppSQLite3Query::CppSQLite3Query()
{
mpDB = 0;
mpStmt = 0;
mnCols = 0;
mbEof = true;
} CppSQLite3Query::CppSQLite3Query(sqlite3 *pdb, sqlite3_stmt *pStmt, bool bEof)
{
mpDB = pdb;
mpStmt = pStmt;
mbEof = bEof;
mnCols = sqlite3_column_count(pStmt);
} CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query &rQuery)
{
mpStmt = rQuery.mpStmt;
const_cast<CppSQLite3Query &>(rQuery).mpStmt = 0;
mnCols = rQuery.mnCols;
mbEof = rQuery.mbEof;
} CppSQLite3Query& CppSQLite3Query::operator =(const CppSQLite3Query &rQuery)
{
mpStmt = rQuery.mpStmt;
const_cast<CppSQLite3Query &>(rQuery).mpStmt = 0;
mnCols = rQuery.mnCols;
mbEof = rQuery.mbEof; return *this;
} CppSQLite3Query::~CppSQLite3Query()
{
Finalize();
} void CppSQLite3Query::CheckStmt()
{
if (mpStmt == 0)
{
throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid Stmt Pointer",
DONT_DELETE_MSG);
}
} int CppSQLite3Query::FieldNums()
{
CheckStmt(); return mnCols;
} //依据字段名返回列索引
int CppSQLite3Query::FieldIndex(const char* szField)
{
CheckStmt(); if (szField)
{
for (int nField = 0; nField < mnCols; nField++)
{
//后面还有非常多相似的函数,參数差点儿相同,须要一个sqlite3_stmt*和列索引值,这应该是内部查询了之后返回的结果,而不是事先保存的
const char *szTemp = sqlite3_column_name(mpStmt, nField);
if (strcmp(szTemp, szField) == 0)
{
return nField;
}
}
} throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid field name requested",
DONT_DELETE_MSG);
}
const char* CppSQLite3Query::FieldName(int nField)
{
CheckStmt(); if (nField < 0 || nField > mnCols-1)
{
throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
} return sqlite3_column_name(mpStmt, nField);
} int CppSQLite3Query::FieldDataType(int nField)
{
CheckStmt(); if (nField < 0 || nField > mnCols-1)
{
throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
} return sqlite3_column_type(mpStmt, nField);
}
const char* CppSQLite3Query::FieldDeclType(int nField)
{
CheckStmt(); if (nField < 0 || nField > mnCols-1)
{
throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
} return sqlite3_column_decltype(mpStmt, nField);
} const char* CppSQLite3Query::FieldValue(int nField)
{
CheckStmt(); if (nField < 0 || nField > mnCols-1)
{
throw CppSQLite3Exception(CPPSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
} return (const char*)sqlite3_column_text(mpStmt, nField); } const char* CppSQLite3Query::FieldValue(const char *szField)
{
int nField = FieldIndex(szField);
return FieldValue(nField);
} bool CppSQLite3Query::FieldIsNull(int nField)
{
return (FieldDataType(nField) == SQLITE_NULL);
} bool CppSQLite3Query::FieldIsNull(const char *szField)
{
int nField = FieldIndex(szField);
return (FieldDataType(nField) == SQLITE_NULL);
} bool CppSQLite3Query::GetIntValue(int nField, int &rDest)
{
if (FieldDataType(nField) == SQLITE_NULL)
{
return false;
}
else
{
rDest = sqlite3_column_int(mpStmt, nField);
return true;
}
} bool CppSQLite3Query::GetIntValue(const char *szField, int &rDest)
{
int nField = FieldIndex(szField);
return GetIntValue(nField, rDest);
} bool CppSQLite3Query::GetFloatValue(int nField, double &rDest)
{
if (FieldDataType(nField) == SQLITE_NULL)
{
return false;
}
else
{
rDest = sqlite3_column_double(mpStmt, nField);
return true;
}
}
bool CppSQLite3Query::GetFloatValue(const char *szField, double &rDest)
{
int nField = FieldIndex(szField);
return GetFloatValue(nField, rDest);
} bool CppSQLite3Query::GetStringValue(int nField, char *&rDest)
{
if (FieldDataType(nField) == SQLITE_NULL)
{
return false;
}
else
{
rDest = const_cast<char *>((const char*)sqlite3_column_text(mpStmt, nField));
return true;
}
}
bool CppSQLite3Query::GetStringValue(const char *szField, char *&rDest)
{
int nField = FieldIndex(szField);
return GetStringValue(nField, rDest);
} bool CppSQLite3Query::Eof()
{
CheckStmt(); return mbEof;
} void CppSQLite3Query::NextRow()
{
CheckStmt(); int nRet = sqlite3_step(mpStmt); if (nRet == SQLITE_DONE)
{
// no rows
mbEof = true;
}
else if (nRet == SQLITE_ROW)
{
// more rows, nothing to do
}
else
{
nRet = sqlite3_finalize(mpStmt);
mpStmt = 0;
const char* szError = sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, szError, DONT_DELETE_MSG);
}
} void CppSQLite3Query::Finalize()
{
if (mpStmt)
{
int nRet = sqlite3_finalize(mpStmt);
mpStmt = 0;
if (nRet != SQLITE_OK)
{
const char* szError = sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, szError, DONT_DELETE_MSG);
}
}
}
C++封装SQLite实例<三>的更多相关文章
- Java项目案例之--封装的实例
Java项目案例之---封装的实例 有一个专业类,有一个专业对象,专业名称:计算机科学与技术,专业编号:J001,专业年限:4,对年限添加约束,如果输入小于0,则默认为0,否则显示输入的值 有一个学生 ...
- 获得 LayoutInflater 实例的三种方式
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...
- [转]获得 LayoutInflater 实例的三种方式
转自:http://www.cnblogs.com/androidez/archive/2013/07/01/3164729.html 获得 LayoutInflater 实例的三种方式 在实际开 ...
- 浅谈学习C++时用到的【封装继承多态】三个概念
封装继承多态这三个概念不是C++特有的,而是所有OOP具有的特性. 由于C++语言支持这三个特性,所以学习C++时不可避免的要理解这些概念. 而在大部分C++教材中这些概念是作为铺垫,接下来就花大部分 ...
- ASP 调用dll(VB)及封装dll实例
ASP调用dll及封装dll实例,封装为dll可以提供运行效率,加密代码. 打开VB6,新建ActiveX DLL 2.在工程引用中加入Microsoft Active Server Pages Ob ...
- IoC容器Autofac之实例优化(三)
回顾之前的代码 //这个类的作用是筛选出MPG类型的电影 public class MPGMovieLister { public Movie[] GetMPG() { var finder = Mo ...
- Java Class类以及获取Class实例的三种方式
T - 由此 Class 对象建模的类的类型.例如,String.class 的类型是Class<String>.如果将被建模的类未知,则使用Class<?>. publi ...
- 一些有用的javascript实例分析(三)
原文:一些有用的javascript实例分析(三) 10 输入两个数字,比较大小 window.onload = function () { var aInput = document.getElem ...
- WCF小实例以及三种宿主
WCF小实例以及三种宿主 最近一直在学习WCF相关知识,下面将通过一个小实例对所学的知识进行简单的回顾:本实例是一个简单三层操作数据库,并且也简单实现的三种宿主(控制台宿主,IIS宿主以及Window ...
随机推荐
- ZOJ 1542 POJ 1861 Network 网络 最小生成树,求最长边,Kruskal算法
题目连接:problemId=542" target="_blank">ZOJ 1542 POJ 1861 Network 网络 Network Time Limi ...
- Eclipse使用总结
Eclipse使用总结 1.Eclipse中出现无法找到Maven包 症状:出现org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER, 且出现无法找 ...
- 被忽视的META标签之特效
在web设计中使用js可以实现很多的页面特效,然而很多人却忽视了HTML标签中META标签的强大功效,其实meta标签也可以实现很多漂亮的页面过渡效果. META标签是HTML语言HEAD区的一个辅助 ...
- 2006 ACM Northwestern European Programming Contest C题(二分求最大)
My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I have a numberN o ...
- perl 异步请求和JS对比
perl 异步和js对比: /js************** $(function(){ function isPhone(str){ var regex = /[0-9]{11,11}/; ret ...
- 【Node.js 自己封装的库 http_parse, libuv】
[Node.js 自己封装的库 http_parse, libuv] Node.js 介绍:一个网络框架,更多:http://www.oschina.net/p/nodejs 官网:http://no ...
- zip非暴力破解
大家最熟悉的zip破解方式应该是暴力破解,暴力破解有很大局限性,如果密码很长很复杂你很可能一辈子都破解不出来.由于今天要破解自己以前加密过的zip文件,我设的密码习惯性长而复杂,果断放弃暴力破解,在网 ...
- 做web项目时对代码改动后浏览器端不生效的应对方法(持续更新)
做web项目时,常常会遇到改动了代码,但浏览器端没有生效,原因是多种多样的,我会依据我遇到的情况逐步更新解决的方法 1.执行的时候採用debug模式,普通情况下使用项目部署button右边那个butt ...
- 在phpmyadmin后台获取webshell方法汇总整理
方法一: CREATE TABLE `mysql`.`xiaoma` (`xiaoma1` TEXT NOT NULL ); INSERT INTO `mysql`.`xiaoma` (`xiaoma ...
- HDU4911-Inversion(树状数组)
Inversion Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tota ...