当前位置: 首页 > 编程日记 > 正文

Swift 中使用 SQLite——查询数据

本文主要介绍如何查询 SQLite 结果集,以及封装 SQLite 的操作方法。

准备测试代码

/// 从数据库中加载 person 数组
class func persons() -> [Person]? {// 1. 准备 SQLlet sql = "SELECT id, name, age, height FROM T_Person;"// 2. 访问数据库// 3. 返回结果return nil
}

在 SQLiteManager 中添加查询语句,准备结果集

/// 执行 SQL 返回查询结果集
///
/// - parameter sql: 任意给定的 SELETE 查询 SQL
func execRecordSet(sql: String) {// 1. 预编译 SQL/**参数1. 已经打开的数据库句柄2. 要执行的 SQL3. 以字节为单位的 SQL 最大长度,传入 -1 会自动计算4. SQL 语句句柄- 后续针对当前查询结果的操作全部基于此句柄- 需要调用 sqlite3_finalize 释放5. 未使用的指针地址,通常传入 nil*/var stmt: COpaquePointer = nilif sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {print("SQL 错误")return}print("SQL 正确")// 2. 遍历集合// 3. 释放语句句柄 - 很重要,否则会内容泄漏sqlite3_finalize(stmt)
}

代码小结

  • 这一部分的工作可以看作是对字符串的 SQL 语句进行编译,并且检查是否存在语法问题
  • 编译成功后通过 sqlite3_step 执行 SQL,每执行一次,获取一条记录
  • 通过 while 循环直至执行完毕
  • 注意,指令执行完毕后需要释放

单步执行

// 2. 单步执行获取结果集内容
var row = 0
while sqlite3_step(stmt) == SQLITE_ROW {print("记录 \(row++)")
}

新建函数负责从 stmt 中获取一条完整的记录

/// 从 stmt 中获取一条完整的记录
///
/// - parameter stmt: stmt
private func record(stmt: COpaquePointer) {print("记录")
}

获取单条记录

所有函数都是以 sqlite3_column_ 开始

  • 获取列数
// 查询结果列数
let colCount = sqlite3_column_count(stmt)
print("列数 \(colCount)")
  • 遍历每一列获取对应的列名数据类型
// 遍历每一列
for col in 0..<colCount {// 列名let cName = sqlite3_column_name(stmt, col)let name = String(CString: cName, encoding: NSUTF8StringEncoding) ?? ""// 数据类型let type = sqlite3_column_type(stmt, col)print("列名 \(name)\(value)")
}

根据不同的数据类型转换对应的数值

  • 小数
var value: AnyObject?
switch type {
case SQLITE_FLOAT:value = sqlite3_column_double(stmt, col)
default:print("不支持的数据类型")
}print("列名 \(name)\(value)")
  • 整数
case SQLITE_INTEGER:value = Int(sqlite3_column_int64(stmt, col))
  • 字符串
case SQLITE3_TEXT:let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, col))value = String(CString: cText, encoding: NSUTF8StringEncoding)
  • 空值
case SQLITE_NULL:value = NSNull()
  • 增加返回值和字典,调整后的代码如下:
/// 从 stmt 中获取当前记录的完整内容
///
/// - parameter stmt: stmt 句柄
private func record(stmt: COpaquePointer) -> [String: AnyObject] {// 1. 获取查询结果列数let colCount = sqlite3_column_count(stmt)// 单条记录字典var row = [String: AnyObject]()// 2. 遍历所有列,获取每一列的信息for col in 0..<colCount {// 1> 获取列名let cName = sqlite3_column_name(stmt, col)let name = String(CString: cName, encoding: NSUTF8StringEncoding) ?? ""// 2> 获取每列数据类型let type = sqlite3_column_type(stmt, col)// 3> 根据数据类型获取对应结果var value: AnyObject?switch(type) {case SQLITE_FLOAT:value = sqlite3_column_double(stmt, col)case SQLITE_INTEGER:value = Int(sqlite3_column_int64(stmt, col))case SQLITE3_TEXT:let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, col))value = String(CString: cText, encoding: NSUTF8StringEncoding)case SQLITE_NULL:value = NSNull()default:print("不支持的数据类型")}//            print("列名 \(name) 值 \(value)")row[name] = value ?? NSNull()}return row
}

完善 execRecordSet 函数

  • 完善 execRecordSet 函数
/// 执行 SQL 返回查询结果集
///
/// - parameter sql: 任意给定的 SELETE 查询 SQL
func execRecordSet(sql: String) -> [[String: AnyObject]]? {// 1. 预编译 SQL/**参数1. 已经打开的数据库句柄2. 要执行的 SQL3. 以字节为单位的 SQL 最大长度,传入 -1 会自动计算4. SQL 语句句柄- 后续针对当前查询结果的操作全部基于此句柄- 需要调用 sqlite3_finalize 释放5. 未使用的指针地址,通常传入 nil*/var stmt: COpaquePointer = nilif sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {print("SQL 错误")return nil}// 创建结果数组var rows = [[String: AnyObject]]()// 2. 遍历集合while sqlite3_step(stmt) == SQLITE_ROW {// 将单条记录字典添加到结果数组中rows.append(record(stmt))}// 3. 释放语句句柄 - 很重要,否则会内容泄漏sqlite3_finalize(stmt)// 4. 返回结果数组return rows
}
  • 在 Person 模型中加载 Person 列表
/// 从数据库中加载 person 数组
class func persons() -> [Person]? {// 1. 准备 SQLlet sql = "SELECT id, name, age, height FROM T_Person;"// 2. 访问数据库获得字典数组guard let rows = SQLiteManager.sharedManager.execRecordSet(sql) else {return nil}// 3. 遍历字典数组 - 字典转模型var arrayM = [Person]()for row in rows {arrayM.append(Person(dict: row))}// 4. 返回结果集合return arrayM
}
  • 测试代码
print((Person.persons() ?? []) as NSArray)

相关文章:

提高C++性能的编程技术笔记:总结

《提高C性能的编程技术》这本书是2011年出版的&#xff0c;书中有些内容的介绍可能已经过时&#xff0c;已不再适用于现在的C编程中&#xff0c;但大部分内容还是很有参考意义的。 这里是基于之前所有笔记的简单总结&#xff0c;笔记列表如下&#xff1a; 跟踪实例&#xff1…

13岁小孩都跟我抢Python了,完了!

以下来自一位程序员母亲和工作人员的对话。程序员妈妈&#xff1a;您好&#xff0c;可以帮我推荐一本适合我家小孩看的编程书籍吗&#xff1f;兔子&#xff1a;可以的呀&#xff0c;《Scratch从入门到精通》&#xff0c;这本书适合小孩学习&#xff0c;您可以先看一下哦~程序员…

Windows Mobile 6.0 SDK和中文模拟器下载

【转】 Windows Mobile 6.0 SDK和中文模拟器下载 Windows Mobile 6.5 模拟器2010年12月06日 星期一 07:48转载自 zhangyanle86终于编辑 zhangyanle86Windows Mobile 6.0 SDK和中文模拟器下载 SDK 6.0下载页面&#xff1a;http://www.microsoft.com/downloads/details.aspx?fam…

wxPython:Python首选的GUI库 | CSDN博文精选

作者 | 天元浪子来源 | CSDN博客文章目录概述窗口程序的基本框架事件和事件驱动菜单栏/工具栏/状态栏动态布局AUI布局DC绘图定时器和线程后记概述跨平台的GUI工具库&#xff0c;较为有名的当属GTK、Qt 和 wxWidgets 了。GTK是C实现的&#xff0c;由于C语言本身不支持OOP&#x…

Swift 中使用 SQLite——修改和删除数据

本文主要介绍在SQLite中修改数据、删除数据&#xff1a; 更新记录 /// 将当前对象信息更新到数据库 /// /// - returns: 是否成功 func updatePerson() -> Bool {guard let name name else {print("姓名不能为空")return false}if id < 0 {print("id 不…

用python3实现指定目录下文件sha256及文件大小统计

有时会统计某个目录下有哪些文件&#xff0c;每个文件的sha256及文件大小等相关信息&#xff0c;这里用python3写了个脚本用来实现此功能&#xff0c;此脚本可跨平台&#xff0c;同时支持windows和linux&#xff0c;脚本(get_dir_file_info.py)内容如下&#xff1a; import os…

Swift 中使用 SQLite——新增数据

本文重点介绍两个方面&#xff0c;1、新增数据&#xff0c;2、获取自动增长 ID。 建立 Person.swift 数据模型 /// 个人模型 class Person: NSObject {// MARK: - 模型属性/// 代号var id: Int64 0/// 姓名var name: String?/// 年龄var age 0/// 身高var height: Double …

投稿2877篇,EMNLP 2019公布4篇最佳论文

整理 | AI科技大本营&#xff08;ID:rgznai100&#xff09;近日&#xff0c;自然语言处理领域的顶级会议之一EMNLP 2019公布了年度最佳论文。EMNLP是由国际语言学会&#xff08;ACL&#xff09;下属的SIGDAT小组主办的自然语言处理领域的顶级国际会议&#xff0c;是自然语言算法…

对象检测工具包mmdetection简介、安装及测试代码

mmdetection是商汤和港中文大学联合开源的基于PyTorch的对象检测工具包&#xff0c;属于香港中文大学多媒体实验室open-mmlab项目的一部分。该工具包提供了已公开发表的多种流行的检测组件&#xff0c;通过这些组件的组合可以迅速搭建出各种检测框架。 mmdetection主要特性&am…

(转)eclipse 代码自动补全

转自&#xff1a;http://blog.csdn.net/yushuwai2010/article/details/11856129 一般默认情况下&#xff0c;Eclipse的代码提示功能是比MicrosoftVisualStudio的差很多的&#xff0c;主要是Eclipse本身有很多选项是默认关闭的&#xff0c;要开发者自己去手动配置。如果开发者不…

swift 多线程GCD和延时调用

GCD 是一种非常方便的使用多线程的方式。通过使用 GCD&#xff0c;我们可以在确保尽量简单的语法的前提下进行灵活的多线程编程。在 “复杂必死” 的多线程编程中&#xff0c;保持简单就是避免错误的金科玉律。好消息是在 Swift 中是可以无缝使用 GCD 的 API 的&#xff0c;而且…

目标检测算法Faster R-CNN简介

在博文https://blog.csdn.net/fengbingchun/article/details/87091740 中对Fast R-CNN进行了简单介绍&#xff0c;这里在Fast R-CNN的基础上简单介绍下Faster R-CNN。 目标检测领域从R-CNN开始&#xff0c;通过引入卷积神经网络取得了很多突破性的进展&#xff0c;但是始终未能…

ICCV 2019 | 加一个任务路由让数百个任务同时跑起来,怎么做到?

作者 | Gjorgji Strezoski, Nanne van Noord, Marcel Worring 译者 | 中国海洋大学李杰 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;摘要传统的多任务&#xff08;MTL&#xff09;学习方法依赖于架构调整和大型可训练参数集来联合优化多个任务。但是&#xff0c;…

DEV开发之控件NavBarControl

右键点击RunDesigner弹出如下界面鼠标先点击3或4,1&#xff0c;&#xff0c;然后点击1或2进行相应的新增或删除操作&#xff0c;3是分组&#xff0c;4是项目&#xff0c;4可以直接拖动到相应的分组3.属性caption:显示的名称4.NavBarControl 属性 PaintStyleName绘画风格&…

swift支持多线程操作数据库类库-CoreDataManager

类库方法 获取数据 executeFetchRequest(request:) 同步获取数据 var request: NSFetchRequest NSFetchRequest(entityName: "MonkeyEntity")var myMonkeys:NSArray? CoreDataManager.shared.executeFetchRequest(request)异步获取数据 executeFetchRequest(re…

目标检测(或分隔)算法Mask R-CNN简介

在博文https://blog.csdn.net/fengbingchun/article/details/87195597 中对Faster R-CNN进行了简单介绍&#xff0c;这里在Faster R-CNN的基础上简单介绍下Mask R-CNN。 Mask R-CNN是faster R-CNN的扩展形式&#xff0c;能够有效地检测图像中的目标&#xff0c;并且Mask R-CNN…

未来之城,管理者可能不是人......

大会官网 https://t.csdnimg.cn/KSTh2010 年&#xff0c;IBM 正式提出了“智慧地球”愿景。在 IBM 的设想中&#xff0c;智慧城市应该由六个核心系统组成&#xff1a;组织&#xff08;人&#xff09;、业务/政务、交通、通讯、水和能源。&#xff08;图源 | IBM 官网&#xff0…

UVa 10701 - Pre, in and post

题目&#xff1a;已知树的前根序&#xff0c;中根序遍历转化成后根序遍历。 分析&#xff1a;递归&#xff0c;DS。依据定义递归求解就可以。 前根序&#xff1a;根&#xff0c;左子树&#xff0c;右子树&#xff1b; 中根序&#xff1a;左子树&#xff0c;根&#xff0c;右子树…

图像集存储成MNIST数据集格式实现

有时会用到将一组图像存放成MNIST中那样的数据格式&#xff0c;以便于用于网络的训练和测试&#xff0c;如MNSIT中的测试集标签t10k-labels.idx1-ubyte和测试集图像t10k-images.idx3-ubyte&#xff0c;各包含了10000个样本&#xff0c;这里以此两个测试集为例详细说明下实现过程…

ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案

原来定位服务是10分钟收不到定位信息就挂起定位&#xff0c;现在变为最短3分钟&#xff0c;估计都是为了省电吧。只要你开启应用的后台定位&#xff0c;并且10分钟有一次定位&#xff0c;那么苹果就不会关闭你的线程&#xff0c;现在变成3分钟。若你的应用开启了后台定位&#…

程序员必知的20个Python技巧

作者 | Duomly 译者 | 弯月&#xff0c;编辑 | 郭芮 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;Python是一门流行且应用广泛的通用编程语言&#xff0c;其应用包括数据科学、机器学习、科学计算等领域&#xff0c;以及后端Web开发、移动和桌面应用程序等方面。…

CSS float浮动的深入研究、详解及拓展(二)

为什么80%的码农都做不了架构师&#xff1f;>>> 接上回… 五、浮动的非本职工作 浮动的本职工作是让匿名inline boxes性质的文字环绕图片显示&#xff0c;而其他所有用浮动实现的效果都不是浮动应该做的事情&#xff0c;我称之为“非本职工作”。 或许我们并没有…

不需要显示地图 就获得用户当前经纬度 超简单的方法

1.遵循协议 CLLocationManagerDelegate,AMapSearchDelegate,AMapLocationManagerDelegate 2. API MAMapServices.sharedServices().apiKey APIKey AMapLocationServices.sharedServices().apiKey APIKey AMapSearchServices.sharedServices().apiKey APIKey AMapNaviService…

ELECTRA:超越BERT,2019年最佳NLP预训练模型

作者 | 李如来源 | NLPCAB&#xff08;ID:rgznai100&#xff09;【导读】BERT推出这一年来&#xff0c;除了XLNet&#xff0c;其他的改进都没带来太多惊喜&#xff0c;无非是越堆越大的模型和数据&#xff0c;以及动辄1024块TPU&#xff0c;让工程师们不知道如何落地。今天要介…

安装node和spm过程

2019独角兽企业重金招聘Python工程师标准>>> 安装nodejs 官网下载nodejs&#xff0c;我下的是v0.10.33版本&#xff0c;安装到d:\nodejs下。 1.新建目录d:\nodejs&#xff0c;在其中建立node_cache、node_global、node_modules三个目录。 2&#xff0c;将C:\Users…

经典网络LeNet-5介绍及代码测试(Caffe, MNIST, C++)

LeNet-5&#xff1a;包含7个层(layer)&#xff0c;如下图所示&#xff1a;输入层没有计算在内&#xff0c;输入图像大小为32*32*1&#xff0c;是针对灰度图进行训练和预测的。论文名字为” Gradient-Based Learning Applied to Document Recognition”&#xff0c;可以直接从ht…

根据经纬度获取用户当前位置信息

根据上篇文章获取的经纬度获取用户当前的位置信息 //获取用户所在位置信息ADDRESS func getUserAddress() { let latitude : CLLocationDegrees LATITUDES! let longitude : CLLocationDegrees LONGITUDES! print("latitude:\(latitude)") print("longitude…

刷了几千道算法题,我私藏的刷题网站都在这里了

作者 | Rocky0429 来源 | Python空间&#xff08;ID: Devtogether&#xff09;遥想当年&#xff0c;机缘巧合入了 ACM 的坑&#xff0c;周边巨擘林立&#xff0c;从此过上了"天天被虐似死狗"的生活...然而我是谁&#xff0c;我可是死狗中的战斗鸡&#xff0c;智力不够…

js实现点击li标签弹出其索引值

据说这是一道笔试题&#xff0c;以下是代码&#xff0c;没什么要文字叙述的&#xff0c;就是点击哪个<li>弹出哪个<li>的索引值即可&#xff1a; <html> <head> <style> li{width:50px;height:30px;margin:5px;float:left;text-align: center;li…

定时器开启和关闭

写程序时遇见了定时器&#xff0c;需要写入数据库用户的经纬 &#xff0c;还要读取&#xff0c;写好之后发现很费电 总结原因&#xff1a; 1&#xff1a;地图定位耗电&#xff08;这个根据程序要求&#xff0c;不能关闭&#xff0c;需要实时定位&#xff0c;很无奈&#xff…