前一篇博客中介绍的是怎样依据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实例&lt;三&gt;的更多相关文章

  1. Java项目案例之--封装的实例

    Java项目案例之---封装的实例 有一个专业类,有一个专业对象,专业名称:计算机科学与技术,专业编号:J001,专业年限:4,对年限添加约束,如果输入小于0,则默认为0,否则显示输入的值 有一个学生 ...

  2. 获得 LayoutInflater 实例的三种方式

    在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...

  3. [转]获得 LayoutInflater 实例的三种方式

    转自:http://www.cnblogs.com/androidez/archive/2013/07/01/3164729.html 获得 LayoutInflater 实例的三种方式   在实际开 ...

  4. 浅谈学习C++时用到的【封装继承多态】三个概念

    封装继承多态这三个概念不是C++特有的,而是所有OOP具有的特性. 由于C++语言支持这三个特性,所以学习C++时不可避免的要理解这些概念. 而在大部分C++教材中这些概念是作为铺垫,接下来就花大部分 ...

  5. ASP 调用dll(VB)及封装dll实例

    ASP调用dll及封装dll实例,封装为dll可以提供运行效率,加密代码. 打开VB6,新建ActiveX DLL 2.在工程引用中加入Microsoft Active Server Pages Ob ...

  6. IoC容器Autofac之实例优化(三)

    回顾之前的代码 //这个类的作用是筛选出MPG类型的电影 public class MPGMovieLister { public Movie[] GetMPG() { var finder = Mo ...

  7. Java Class类以及获取Class实例的三种方式

    T - 由此 Class 对象建模的类的类型.例如,String.class 的类型是Class<String>.如果将被建模的类未知,则使用Class<?>.   publi ...

  8. 一些有用的javascript实例分析(三)

    原文:一些有用的javascript实例分析(三) 10 输入两个数字,比较大小 window.onload = function () { var aInput = document.getElem ...

  9. WCF小实例以及三种宿主

    WCF小实例以及三种宿主 最近一直在学习WCF相关知识,下面将通过一个小实例对所学的知识进行简单的回顾:本实例是一个简单三层操作数据库,并且也简单实现的三种宿主(控制台宿主,IIS宿主以及Window ...

随机推荐

  1. Google App Engine 学习和实践

    这个周末玩了玩Google App Engine,随手写点东西,算是学习笔记吧.不当之处,请多多指正. 作者:liigo,2009/04/26夜,大连 原创链接:http://blog.csdn.ne ...

  2. 测试framebuffer

    static GGLContext *gr_context = 0; static GGLSurface gr_framebuffer[2]; static unsigned gr_active_fb ...

  3. Http请求工具实例编写(超长,比较清楚)

    HTTP协议工作方式首先客户端发送一个请求(request)给服务器,服务器在接收到这个请求后将生成一个响应(response)返回给客户端.在这个通信的过程中HTTP协议在以下4个方面做了规定:1. ...

  4. javascript json格式解析方法

    json.parse用于从一个字符串中解析出json对象 stringify()用于从一个对象解析出字符串 var dataObj = eval("("+json+")& ...

  5. JavaScript快速入门(四)——JavaScript函数

    函数声明 之前说的三种函数声明中(参见JavaScript快速入门(二)——JavaScript变量),使用Function构造函数的声明方法比较少见,我们暂时不提.function func() { ...

  6. JavaScript移除数组元素

    //数组移除长度方法 var array=[]; array[0]="张三"; array[1]="李四"; array[2]="王五"; ...

  7. RGB HSV HLS三种色彩模式转换(C语言实现)

    Android项目上处理图像的代码(注释全部去掉) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...

  8. badi增强

    对于根据事务代码查找对应的BADI,网上介绍的方法很多,但总结下来无非就两种方法,在此把它记录下来,方便以后自己查阅了. (1)通过SE24,输入CL_EXITHANDLER,然后在方法GET_INS ...

  9. React-TodoList

    React入门最好的学习实例-TodoList 前言 React 的核心思想是:封装组件,各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件. 最近前端界闹的沸沸扬扬的技术当属react ...

  10. 【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME

    原文:[ASP.NET Web API教程]5.3 发送HTML表单数据:文件上传与多部分MIME 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面 ...