swift使用mysql教程,Swift学习教程之SQLite的基础使用

前言

在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高APP的用户体验。

SQLite就是我们实现本地数据缓存的一种方案,SQLite有以下优点:iOS内嵌SQLite;经过时间的验证;开源;跨平台。

OK,废话不多说,现在我们就开始进入SQLite的体验之旅。当然在开始之前我们要做一点准备工作,毕竟我们不打没有准备的仗。

准备工作

创建备用数据

导入SQLite3:import SQLite3

创建一个Goods的类用来表示数据库存储的数据类型

创建一个Goods类型的数组

声明一个dbPath和db的全局变量,声明一个获取libraryDirectory路径的函数(数据库存放路径如何选择)

代码如下:

class Goods {

let name: String!

let weight: Int!

var price: Double!

init(name: String, weight: Int, price: Double) {

self.name = name

self.weight = weight

self.price = price

}

}

let goods = Goods(name: "computer", weight: 10, price: 2000.0)

var goodArr = [Goods]()

var dbPath = ""

var db: OpaquePointer?

func createData() {

for index in 0...4 {

let goods = Goods(name: "computer" + "\(index)", weight: index * 10, price: 20.0)

goodArr.append(goods)

}

}

func fetchLibraryPath() {

if let libraryPathString = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {

let pathURL = URL(fileURLWithPath: libraryPathString).appendingPathComponent("goods.sqlite")

dbPath = pathURL.path

}

}

创建并连接数据库

func openDatabase() -> OpaquePointer? {

var db: OpaquePointer?

if sqlite3_open(dbPath, &db) == SQLITE_OK {

resultLabel.text = "成功打开数据库,路径:\(dbPath)"

return db

} else {

resultLabel.text = "打开数据库失败"

return nil

}

}

通过上面的代码我们可以看到,首先声明了一个OpaquePointer类型的可选值db,接下来调用了sqlite3_open()方法,该方法的作用是:如果之前创建了数据库那么直接打开,若没创建会直接创建一个。如果该方法调用成功,他会返回一个OpaquePointer的值赋值给你传递进去的db。

SQLITE_OK是一个定义在SQLite库中的一个常量,它代表一个Int32的0。SQLite的大多数函数都会返回一个Int32的值,例如SQLITE_ROW (100)、SQLITE_DONE (101)等,详细列表你可以查看这里。

现在你可以通过调用db = openDatabase()来打开或者创建一个数据库了,正常情况下你会看见成功打开数据库,路径:xxx/xxx.sqlite的输出。

现在,我们已经成功的创建了一个名字为goods.sqlite的数据库了,接下来我们要做的就是创建一个表了。

创建表

代码

func createTable() {

let createTableString = """

CREATE TABLE Computer(

Id INT PRIMARY KEY NOT NULL,

Name CHAR(255),

Weight Int,

Price Float);

"""

var createTableStatement: OpaquePointer?

// 第一步

if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {

// 第二步

if sqlite3_step(createTableStatement) == SQLITE_DONE {

resultLabel.text = "成功创建表"

} else {

resultLabel.text = "未成功创建表"

}

} else {

}

//第三步

sqlite3_finalize(createTableStatement)

}

代码说明

首先解释一下createTableString:创建一个名字为Computer的表,Id为主键且不为空,Name不超过255个字符,Weight为Int类型,Price为Float类型。

然后创建了一个OpaquePointer?类型的变量用于下面的函数:sqlite3_prepare_v2()。

第一步:该函数会将createTableString编译为字节代码(byte code)并返回一个status code,这个函数执行成功则表明database已经准备好了执行任意的SQL statement(就是创建的SQL的字符串),该函数执行成功后即会执行sqlite3_step()。

第二步:sqlite3_step()用来执行编译完成的statement handle(createTableStatement)并返回一个status code。

第三步:在你每一次的操作完成后你必须调用sqlite3_finalize()去删除你的statement以避免resource leak。注意:一旦一个statement被finalized,你不应该再一次使用它。

插入一条数据

代码

func insertOneData() {

let insertRowString = "INSERT INTO Computer (Id, Name, Weight, Price) VALUES (?, ?, ?, ?);"

var insertStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, insertRowString, -1, &insertStatement, nil) == SQLITE_OK {

let id: Int32 = 1

//第二步

sqlite3_bind_int(insertStatement, 1, id)

sqlite3_bind_text(insertStatement, 2, goods.name, -1, nil)

sqlite3_bind_int(insertStatement, 3, Int32(goods.weight))

sqlite3_bind_double(insertStatement, 4, goods.price)

//第三步

if sqlite3_step(insertStatement) == SQLITE_DONE {

resultLabel.text = "插入数据成功"

} else {

resultLabel.text = "插入数据失败"

}

} else {

}

//第四步

sqlite3_finalize(insertStatement)

}

代码说明

insertRowString中的?和前面的字段是对应的,它只是占位符的意思,告诉编译器当真正执行该语句的时候会插入相应的值。

第二步:sqlite3_bind_int()标识你绑定了一个Int类型的值,该函数的第一个参数是你的statement(即insertStatement),第二个参数是?的位置在你的statement(注意该值是非零的),在此处也就是1,第三个参数为你想绑定的值。sqlite3_bind_text()函数表示你绑定的是一个text(一般用于比较长的字符串)类型值,该函数比sqlite3_bind_int()多了额外的两个参数,第四个参数的意思是text的字节数,一般穿-1,第五个参数是一个closure回调,处理完string后调用。

第三步第四步同上

插入多条数据

代码

func insertMutipleData() {

let insertRowString = "INSERT INTO Computer (Id, Name, Weight, Price) VALUES (?, ?, ?, ?);"

var insertStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, insertRowString, -1, &insertStatement, nil) == SQLITE_OK {

for (index, good) in goodArr.enumerated() {

let id: Int32 = Int32(index + 1)

//第二步

sqlite3_bind_int(insertStatement, 1, id)

sqlite3_bind_text(insertStatement, 2, good.name, -1, nil)

sqlite3_bind_int(insertStatement, 3, Int32(good.weight))

sqlite3_bind_double(insertStatement, 4, good.price)

//第三步

if sqlite3_step(insertStatement) == SQLITE_DONE {

resultLabel.text = "插入数据成功"

} else {

resultLabel.text = "插入数据失败"

}

//第四步

sqlite3_reset(insertStatement)

}

} else {

}

//第五步

sqlite3_finalize(insertStatement)

}

代码说明

insertRowString同上。

第四步:调用sqlite3_reset()函数,以便下次循环再次执行insertStatement

第一步、第二步、第三步、第五步同上。

更新数据

代码

func updateData() {

let updateString = "UPDATE Computer SET Name = 'changeComputer' WHERE Id = 2;"

var updateStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, updateString, -1, &updateStatement, nil) == SQLITE_OK {

//第二步

if sqlite3_step(updateStatement) == SQLITE_DONE {

resultLabel.text = "更新成功"

} else {

}

}

//第三步

sqlite3_finalize(updateStatement)

}

代码说明

updateString:将Id==2的数据的Name字段改为changeComputer。

sqlite3_prepare_v2():准备,sqlite3_step():执行更新statement,sqlite3_finalize():结束。

删除数据

代码

func deleteData() {

let deleteString = "DELETE FROM Computer WHERE Id = 2;"

var deleteStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, deleteString, -1, &deleteStatement, nil) == SQLITE_OK {

//第二步

if sqlite3_step(deleteStatement) == SQLITE_DONE {

resultLabel.text = "删除成功"

}

} else {

}

//第三步

sqlite3_finalize(deleteStatement)

}

代码说明

deleteString:删除表中Id==2的数据。

sqlite3_prepare_v2():准备,sqlite3_step():执行删除statement,sqlite3_finalize():结束。

查询一条数据

代码

func queryOneData() {

let queryString = "SELECT * FROM Computer WHERE Id == 2;"

var queryStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK {

//第二步

if sqlite3_step(queryStatement) == SQLITE_ROW {

//第三步

let id = sqlite3_column_int(queryStatement, 0)

let queryResultName = sqlite3_column_text(queryStatement, 1)

let name = String(cString: queryResultName!)

let weight = sqlite3_column_int(queryStatement, 2)

let price = sqlite3_column_double(queryStatement, 3)

resultLabel.text = "id: \(id), name: \(name), weight: \(weight), price: \(price)"

} else {

resultLabel.text = "error"

}

}

//第四步

sqlite3_finalize(queryStatement)

}

代码说明

queryString:在Computer表中查找所有Id == 2的数据。

第二步:注意此时要判断的status code为SQLITE_ROW,如果该判断为true则代表你查询的数据存在在表里。

第三步:sqlite3_column_int()函数是按照列数取数据,第一个参数是statement,第二个参数则是该字段是第几列(Id 为表里的第一列,从0开始计算)。sqlite3_column_text()要略微复杂一点,他需要转换类型通过String(cString: queryResultName!)。

第一步、第四步同上

查询多条数据

代码

func queryAllData() {

let queryString = "SELECT * FROM Computer;"

var queryStatement: OpaquePointer?

//第一步

if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK {

//第二步

while(sqlite3_step(queryStatement) == SQLITE_ROW) {

//第三步

let id = sqlite3_column_int(queryStatement, 0)

let queryResultName = sqlite3_column_text(queryStatement, 1)

let name = String(cString: queryResultName!)

let weight = sqlite3_column_int(queryStatement, 2)

let price = sqlite3_column_double(queryStatement, 3)

resultLabel.text = "id: \(id), name: \(name), weight: \(weight), price: \(price)"

}

}

//第四步

sqlite3_finalize(queryStatement)

}

代码说明

第二步:此处为while循环,当查询到最后一行时会返回SQLITE_DONE状态码来结束。

第一步第三步第四步同上。

小结

通过上面我们可以总结出执行一个statement的大概流程:sqlite3_prepare_v2():准备,sqlite3_step():执行statement,sqlite3_finalize():结束。好了,到这里SQLite3的增删改查基本操作也就完事了。下一篇我们来了解一下SQLite的进阶用法。Bye~

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558510.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用c++查看linux服务器某个进程正在使用的内存_精选20个常用的Linux命令

今天总结几个非常常用的Linux命令,其中有几个在面试中很可能问相关命令的原理,比如后台运行命令。希望对大家有所帮助,最好自己去尝试在Linux操作系统中实践一下。1 查看目录以及权限在windows中,使用dir查看当前目录中文件。在Li…

php数组如何去掉相同的元素,如何去掉php数组中的重复的元素

如何去掉php数组中的重复的元素发布时间:2020-07-30 09:49:32来源:亿速云阅读:74作者:Leah今天就跟大家聊聊有关如何去掉php数组中的重复的元素,可能很多人都不太了解,为了让大家更加了解,小编给…

台式电脑可以连wifi吗_不使用WIFI,手机也可以通过电脑的网络上网

让手机通过电脑上网的方式有很多种,最常见的就是 WIFI 了,而且简单直接。但是有时候台式机没有 WIFI ,或者电脑的 WIFI 设备已经连接到其他的网络了,这时候手机就不能通过电脑的 WIFI 连接到网络。那么还没有有办法连接到网络呢&a…

php架在底部页面,页脚始终保持在页面底部的网页布局方法

页脚始终保持在页面底部的网页布局方法导语:用CSS创建一个高度自适应布局,如何保证页脚(footer)在内容不超过一屏的情况下始终保持在布局最下方是一个比较头疼的事。下面就由百分网小编为大家介绍一下页脚始终保持在页面底部的网页布局方法,希…

pgsql 前10条_未来3年,广州83条城中村、285个旧街区将迎来改造

文、图/羊城晚报全媒体记者 赵燕华 通讯员 穗建未来3年,广州83条城中村将实施改造,285个旧街区将迎来改造,推进176个旧厂房改造,将整治1.24亿平方米违建……9月25日,在广州市深化城市更新工作推进高质量发展政策培训暨…

Linux版本Oracle工具,Linux下oracle可视化操作工具sqldeveloper安装与配置

一、Oracle SQL Developer 3.2.2 选择Linux RPM版本下载1、安装sqldeveloper,rpm -ivh sqldeveloper-3.2.20.09.87-1.noarch.rpm,安装完成后软件在/opt/sqldeveloper, 虽然在程序菜单中有sql-developer的图标,但单击并不能启动,估…

c++能干什么_「CG原画插画教程」学画画到底能干什么?

原标题:「CG原画插画教程」学画画到底能干什么?艺学绘小编收集整理了学画画到底能干什么?学画画到底能干什么?相信很多学画画的朋友们都被问过这个问题,那些对学画画有偏见的人,总觉得我们在“不务正业”。…

查看oracle空间使用率,Oracle 查看表空间使用率

1.查询不包含临时表空间的使用率SELECT Upper(F.TABLESPACE_NAME) "TablespaceName",D.TOT_GROOTTE_MB "Total(M)",D.TOT_GROOTTE_MB - F.TOTAL_BYTES "Used(M)",To_char(Round(( D.TOT_GROOTTE_MB - F.TOTAL_BYTES ) / D.TOT_GROOTTE_MB * 100,…

怎样设置电脑壁纸_怎样设置电脑的资料定时备份到移动硬盘里

怎样设置电脑的资料定时备份到移动硬盘里 写回答...安装FreeFileSync即可,功能有:自动备份、单向备份、双向备份、更新指定文件夹、增量更新、定时备份等。你安装后,添加一个批处理任务来执行将电脑的资料定时备份到移动硬盘。选:…

packetbeat oracle,packetbeat 无法启动

抓到了一些包,但是没有看到视频中的http的包:都是些UDP2018/08/12 10:46:27.756161 sniffer.go:145: INFO Resolved device index 1 to device: \Device\NPF_{5E472DB4-3BFB-4696-A0DF-4A1BA12EBEB3}2018/08/12 10:46:27.812161 beat.go:233: INFO packe…

appium自动化测试_Appium自动化测试入门教程No.1—— Appium介绍

(1)特点appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web应用和混合应用。>>“移动原生应用”是指那些用iOS或者 Android SDK 写的应用(Application简称app)。>>“移动web应用”是指使用移动浏览器访问的应用…

linux 命令行看图片,骚操作:用终端打开图片

导读Linux 上有许多 GUI 图片浏览器。但我尚未听说或使用过任何在终端中显示图片的应用程序。幸运的是,我刚刚发现了一个可用于在终端中显示图像的名叫 FIM 的图像查看器。FIM 引起了我的注意,是因为与大多数 GUI 图片浏览器相比,它非常轻巧。…

python中使用什么命令进入帮助系统-python中os模块中文帮助

python中os模块中文帮助文档 文章分类:Python编程 python中os模块中文帮助文档 翻译者:butalnd 翻译于2010.1.7——2010.1.8,个人博客:http://butlandblog.appspot.com/ 注此模块中关于unix中的函数大部分都被略过,翻译主要针对WI…

linux 登入用户记录,linux记录所有用户登陆及执行过的命令脚本

第一个窗口[roothdss7-4 ~]# echo "historyUSERwhoamiUSER_IPwho -u am i 2>/dev/null| awk {print $NF}|sed -e s/[()]//gif [ "$USER_IP" "" ]; thenUSER_IPhostname ## 获取ip 并且存到变量中fiif [ ! -d /var/log/history ]; thenmkdir /var/…

线程被中断跟被阻塞有什么区别_宠物加盟店跟自营店有什么区别

宠物加盟店跟自营店有什么区别开宠物店是一个很有发展、很有市场前景的项目,特别是在这几年,已经迅猛发展。如果想加入宠物行业,利润、赚钱、前景都不用担心,只要有愿意做成的心,市场大环境不用担心。关于大家提出的宠…

linux装nvidia驱动没有图形界面,[转]Fedora 13下安装Nvidia显卡驱动的方法/Linux无法进入X Windows 图形界面的解决方法...

再试一试这个方法:[转自]http://www.myexception.cn/image/505352.htmlVirtualBox3.1.2安装Fedora12后无法启动图形界面问题VirtualBox真是个好东东,无缝模式集成进windows,一边能玩windows下的游戏啊,QQ啊,又可以不耽…

不超过20位的小数正则_意甲身价最贵的20位球星,国米多达7人超过尤文,夺冠成硬任务...

根据《德转网》的最新统计,在本赛季意甲身价排名前20位的球星当中,国际米兰俱乐部拥有多达7人,比起意甲霸主尤文图斯还要多出2人。这7位国米球星分别是卢卡库(意甲球员身价第一,8000万欧元)、马丁内斯(意甲球员身价第四、4000万欧…

mcp证书有什么用_建造师的行情怎么样呢?建造师证书有什么用?

近年来,一二级建造师报名人数的逐年递增。从2004年至今,从当初几万人报考到现在的几百万人报考,这些都说明了大家都意识到了建造师证书的重要性。因为要用到证书的地方太多了,建筑企业升级资质要求建造师证书、企业年检要求建造师…

linux环境变量命名规范,Linux就该这么学 -- 重要的环境变量

变量是计算机系统用于保存可变值的数据类型。在Linux中,变量名一般都是大写,这是一种约定俗成的规范,我们可以直接通过变量名称来提取到对应的变量值。用户执行一条命令,Linux系统一般分为4个步骤第一步:判断用户是否以…

realtek audio console无法连接rpc服务_RPC服务在游戏中的简单运用

作者:二周目赤出处:https://www.cnblogs.com/cr1719/p/13866841.html我们最开始做的游戏框架,多数都是client—>server—>db的模式,但是随着玩家数量的增加,一个server进程就会扛不住,需要多个进程服务于多个玩家。但是给定…