当前位置: 首页 > news >正文

Windows Mobile下访问Sqlite的Native C++封装

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

Sqlite源码

Sqlite源码可以到 SQLite Download Page 下载,我为了省事直接使用了sqlite.phxsoftware.com的在Windows Mobile下的build工程。

Sqlite的C++封装

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

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

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

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

4. CppSQLite3Exception 用于捕捉异常。

简单明了的封装了Sqlite。

封装类的使用

使用方法源自于我对CppSQLite3U类的单元测试。见源文件的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数据类型定义信息是和具体的数据绑定的而不是和字段定义绑定,也就是动态的,同一个字段的不同记录可以存储不同的数据类型的数据。所以在定义表的时候定义字段类型不是必须的,具体可以参考 Datatypes In SQLite Version 3。

执行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<max; ++i) { SYSTEMTIME currentTime; GetLocalTime(&currentTime); sqlStr.Format(L"INSERT INTO T1 (F1, F2, F3) VALUES(%d, 'STR%d', '%d-%d-%d %d:%d:%d')", i, i, currentTime.wYear, currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond); db.execDML(sqlStr); } tmEnd = time(0); char ch[255]; sprintf(ch, "Insert table successful in %d seconds", tmEnd-tmStart); TRACE(ch); db.close(); } catch(CppSQLite3Exception e) { FAIL(ToString(e.errorMessage()).c_str()); } }

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的SqlCommand.ExecuteScalar 用于取第一条记录的一个字段的值,一般用于聚集函数的查询。

执行查询

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<max; ++i) { SYSTEMTIME currentTime; GetLocalTime(&currentTime); sqlStr.Format(L"INSERT INTO T1 (F1, F2, F3) VALUES(%d, 'STR%d', '%d-%d-%d %d:%d:%d')", i, i, currentTime.wYear, currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond); db.execDML(sqlStr); } db.execDML(L"commit transaction;"); tmEnd = time(0); char ch[255];
http://www.jsqmd.com/news/1132362/

相关文章:

  • 数据分析转大模型:换个角度,从方案设计到上线检查
  • 域名与DNS批量管理实战:OpenClaw自动解析检测、批量修改与监控全攻略
  • Google chrome OS vmdk文件在WMware下运行的办法
  • TFT-LCD 驱动架构对比:4 种 Cs 存储电容布局的优缺点与选型指南
  • 高空航拍地面建筑物数据集7682张VOC+YOLO格式
  • 多品牌集合店营收分配程序,测算设计师品牌,快时尚,奢品搭配销售最优比例。
  • 商用轨道插座怎么选更划算 各品牌性价比盘点帮你避坑少花冤枉钱
  • JD Cloud 验证码逆向
  • 【全文系列目录】风控PM记
  • Burp Suite Intruder 4种攻击模式实战:Sniper/Cluster Bomb 对比与 3 个典型场景应用
  • LLM的“类人认知“,到底是能力涌现还是统计模仿?
  • XCA 2.9.0:企业级PKI证书管理的技术架构与实战解决方案
  • 私密科普:女性经后淋漓不尽,别当成普通经期残留
  • 终极指南:企业级Docker化邮件中继服务部署与架构实践
  • 机房故障换机后应急验证:24 小时 SpeedCE 点检 SOP
  • AI编程助手实战指南:从原理到应用,GitHub Copilot与Cursor深度测评
  • 【操作系统】页面置换算法(CLOCK/改进型CLOCK)
  • Redis--Redis分布式系统的原理与实操
  • 你的前端代码打包后究竟经历了什么?
  • 白话MVP
  • Agent出现LLM因为历史工具调用消息而误解工具调用方式的问题
  • Gromacs 分子动力学 远程安装介绍 全网最详细的Gromacs安装前说明 该怎么选择合适的安装方式 Windows直接可用的Gromacs(预编译版)有什么危害?Gromacs安装需要准备什么?
  • Langchain文本切割器在RAG中的使用
  • K/R/F/S 四大系列斜齿轮减速机的区别与选型要点?
  • Cline 配置 Claude Sonnet 5 实战指南:思考深度调优与切换 Fable 5 的时机
  • 3步解锁Text-to-CAD:如何用文字描述生成专业机械设计
  • Pandoc Lua 过滤器:免外部工具,高效处理文档转换!
  • 图最短路评测:Dijkstra 对了,也可能用错场景
  • [实例] SPI接口的ADC芯片全通道纯硬件驱动——基于HAL库和TLA2518芯片
  • 74LS73 异步计数器设计实战:2片芯片实现4位二进制与8421BCD电路对比