博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Mobile下访问Sqlite的Native C++封装
阅读量:6610 次
发布时间:2019-06-24

本文共 3670 字,大约阅读时间需要 12 分钟。

背景

当前移动设备开发领域,在本地数据存储方面,Sqlite几乎成了事实标准,Andriod (),iPhone ( 和 ),Palm WebOS (),新版本的Symbian也直接built-in Sqlite了()。那么作为移动设备领域的重要一员Windows Mobile怎么可能错过Sqlite呢。

 

简介

Sqlite几乎成立移动设备开发领域数据存储方面的事实标准。Sqlite已经广泛被使用到Andriod,iPhone,WebOS以及Symbian等平台了,本文讲述在Windows Mobile平台下如何使用Native C++访问Sqlite,同时讲述一个封装类的实现和使用。

 

Sqlite源码

Sqlite源码可以到  下载,我为了省事直接使用了的在Windows Mobile下的build工程。

 

Sqlite的C++封装

封装我使用了的封装。这里感谢的推荐。封装是对Sqlite原有纯C的api进行OO的C++的封装。主要封装以下几个类:

1. CppSQLite3DB 数据库类,用于新建数据库,打开关闭链接,执行DDL和DML。

2. CppSQLite3Statement 用于执行参数化的SQL。CppSQLite3DB 可以执行SQL但是不支持参数化。

3. CppSQLite3Query 用于读出执行Select后的查询结果。

4. CppSQLite3Exception 用于捕捉异常。

简单明了的封装了Sqlite。

 

封装类的使用

使用方法源自于我对类的单元测试。见源文件的SqliteHelperTest.h。

 

创建数据库文件

TEST(SqliteHelper, CreateDatabase) {
try {
CppSQLite3DB db; DeleteFile(DB_FILE_NAME); db.open(DB_FILE_NAME); db.close(); } catch(CppSQLite3Exception e) {
FAIL(ToString(e.errorMessage()).c_str()); } TRACE("Create database successful."); }

调用CppSQLite3DB 的open()函数的时候如果发现没有数据库文件就会新建一个数据库文件。Sqlite的源代码如下(见sqlite3.c):

rc = openDatabase(zFilename8, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);

 

执行DDL

TEST(SqliteHelper, CreateTable) {
try {
CppSQLite3DB db; db.open(DB_FILE_NAME); db.execDML(L"create table T1(F1 int, F2 char(20), F3 char(20));"); db.close(); } catch(CppSQLite3Exception e) {
FAIL(ToString(e.errorMessage()).c_str()); } TRACE("Create table successful."); }

执行CppSQLite3DB 的execDML()函数可以执行DDL。Sqlite3的数据类型定义和其他常见关系型数据库有很大区别,Sqlite3数据类型定义信息是和具体的数据绑定的而不是和字段定义绑定,也就是动态的,同一个字段的不同记录可以存储不同的数据类型的数据。所以在定义表的时候定义字段类型不是必须的,具体可以参考 。

 

执行DML

TEST(SqliteHelper, InsertTable) {
try {
CppSQLite3DB db; db.open(DB_FILE_NAME); CString sqlStr; time_t tmStart, tmEnd; tmStart = time(0); for(int i=0; i

CppSQLite3DB 的execDML()函数不仅可以执行DDL,而且可以执行DML。同理Update和Delete语句一样。

 

执行Scalar

TEST(SqliteHelper, SelectScalarBeforeInsert) {
try {
CppSQLite3DB db; db.open(DB_FILE_NAME); int count = db.execScalar(L"SELECT COUNT(*) FROM T1;"); char ch[255]; sprintf(ch, "%d rows in T1 table", count); TRACE(ch); db.close(); } catch(CppSQLite3Exception e) {
FAIL(ToString(e.errorMessage()).c_str()); } TRACE("Select scalar before insert successful."); }

CppSQLite3DB 的execScalar()函数模仿ADO.NET的 用于取第一条记录的一个字段的值,一般用于聚集函数的查询。

 

执行查询

TEST(SqliteHelper, SelectAfterInsert) {
try {
CppSQLite3DB db; db.open(DB_FILE_NAME); CppSQLite3Query q = db.execQuery(L"SELECT * FROM T1;"); std::string str; char ch[255]; while (!q.eof()) {
sprintf(ch, "F1=%d, F2=%S, F3=%S\n", q.getIntField(0), q.getStringField(1), q.getStringField(2)); str += ch; q.nextRow(); } TRACE(str.c_str()); db.close(); } catch(CppSQLite3Exception e) {
FAIL(ToString(e.errorMessage()).c_str()); } }

查询需要借助CppSQLite3Query 来取出查询的结果。eof()函数判断是否结束。nextRow()移动到下一条记录。getIntField()函数和getStringField()函数为读取当前记录的特定字段的值。

 

使用事务

TEST(SqliteHelper, InsertTableWithTransaction) {
try {
CppSQLite3DB db; db.open(DB_FILE_NAME); CString sqlStr; time_t tmStart, tmEnd; tmStart = time(0); db.execDML(L"begin transaction;"); for(int i=0; i

在Sqlite上事务的使用非常简单。通过CppSQLite3DB 的execDML()函数来打开,提交和回退事务。Sqlite在事务处理上,语法层面上和MS SQL Server有点类似,默认是自动事务(AutoCommit),关于事务处理我之前写过一篇文章,有兴趣可以参考下 。也可以参考

。 从测试结果看,批量处理数据,显式使用事务和自动事务在处理时间上差别很大。

在insert 100条数据时,显式使用事务小于1秒钟完成,而使用自动事务的话需要4秒钟。为什么有这么大的差别,我没有仔细研究Sqlite的源码,我从通用数据库的概念来讲述,事务其中一个特性是持久性(Durability),也就是凡是提交了的事务的数据都需要持久化,需要持久化就需要写硬盘,在移动设备是flash,写永久存储设备的速度是远远慢于写内存的速度的,所以速度差异点在IO。

 

Unit Test

项目开发中使用了TDD,关于Unit Test可以参考
 和 
 。

 

关于项目

我把项目host到codeplex了,项目主页链接如下:

检查和下载最新版本链接如下

 

如果你喜欢这个项目,如果这些代码能帮助你,请回复,上次我做了一个SqlCeHelper,参考 。某一天我收到一个消息,一个人告诉我他google了一个星期也没一个搞定SqlCe,看了我的文章搞定了,我还是很高兴能帮到别人。

    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/10/19/Sqlite_CPP.html,如需转载请自行联系原作者

你可能感兴趣的文章
【摘】人生苦短, 每日python
查看>>
【转】聚集索引和非聚集索引的区别
查看>>
【转】mac os 安装php
查看>>
C# DllImport的用法
查看>>
Github-Client(ANDROID)开源之旅(二) ------ 浅析ActionBarSherkLock
查看>>
no identities are available for signing
查看>>
javascript 和 jquery插件开发
查看>>
Linux Shell文件差集
查看>>
eclipse中如何去除警告:Class is a raw type. References to generic type Class<T> should be parameterized...
查看>>
Gradle脚本基础全攻略
查看>>
Django模版中的过滤器详细解析 Django filter大全
查看>>
Linux中使用pwconv实现passwd中密码到shadow
查看>>
MongoDB C++ gridfs worked example
查看>>
Visual Studio 2017各版本安装包离线下载
查看>>
C#线程安全的那些事
查看>>
【论文笔记】Social Role-Aware Emotion Contagion in Image Social Networks
查看>>
rpm安装PostgreSQL
查看>>
k sum(lintcode)
查看>>
28. extjs中Ext.BLANK_IMAGE_URL的作用
查看>>
Hibernate注解配置N:N关联
查看>>