C++封装SQlite<三>

文章转自:http://blog.csdn.net/zlhy_/article/details/8722920

查看更多的SQlite的C/C++函数接口:http://www.sqlite.org/c3ref/funclist.html

 

前一篇博客中介绍的是如何根据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);
		}
	}
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLite是一种轻型的嵌入式关系型数据库,它不需要独立的服务器进程,以文件的形式存储数据,因此非常适合嵌入到其他应用程序中使用。在C++中,我们可以通过SQLite提供的C接口来操作SQLite数据库,也可以通过封装SQLite的方式来简化操作。 下面是一个简单的C++封装SQLite3的示例: ```cpp #include <sqlite3.h> #include <string> class SQLiteDB { public: SQLiteDB(const std::string& dbPath) : dbPath_(dbPath), db_(nullptr) {} ~SQLiteDB() { close(); } bool open() { if (db_) { return true; } int result = sqlite3_open(dbPath_.c_str(), &db_); if (result != SQLITE_OK) { return false; } return true; } void close() { if (db_) { sqlite3_close(db_); db_ = nullptr; } } bool exec(const std::string& sql) { char* error = nullptr; int result = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error); if (result != SQLITE_OK) { sqlite3_free(error); return false; } return true; } private: std::string dbPath_; sqlite3* db_; }; ``` 以上代码定义了一个SQLiteDB类,它包含了打开和关闭数据库的方法,以及执行SQL语句的方法。在构造函数中,我们需要传入数据库文件的路径,通过sqlite3_open函数打开数据库,如果打开失败则返回false。在析构函数中,我们需要关闭数据库。在exec方法中,我们通过sqlite3_exec函数执行SQL语句,如果执行失败则返回false。 使用示例: ```cpp int main() { SQLiteDB db("test.db"); if (!db.open()) { return -1; } if (!db.exec("CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT)")) { return -1; } if (!db.exec("INSERT INTO user (name) VALUES ('Tom')")) { return -1; } db.close(); return 0; } ``` 以上代码创建了一个名为test.db的SQLite数据库文件,并在其中创建了一个名为user的表,然后插入了一行数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值