Swift学习教程之SQLite的基础使用
前言
在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高APP的用户体验。
SQLite就是我们实现本地数据缓存的一种方案,SQLite有以下优点:iOS内嵌SQLite;经过时间的验证;开源;跨平台。
OK,废话不多说,现在我们就开始进入SQLite的体验之旅。当然在开始之前我们要做一点准备工作,毕竟我们不打没有准备的仗。
准备工作
创建备用数据
- 导入SQLite3:importSQLite3
- 创建一个Goods的类用来表示数据库存储的数据类型
- 创建一个Goods类型的数组
- 声明一个dbPath和db的全局变量,声明一个获取libraryDirectory路径的函数(数据库存放路径如何选择)
代码如下:
classGoods{ letname:String! letweight:Int! varprice:Double! init(name:String,weight:Int,price:Double){ self.name=name self.weight=weight self.price=price } } letgoods=Goods(name:"computer",weight:10,price:2000.0) vargoodArr=[Goods]() vardbPath="" vardb:OpaquePointer? funccreateData(){ forindexin0...4{ letgoods=Goods(name:"computer"+"\(index)",weight:index*10,price:20.0) goodArr.append(goods) } } funcfetchLibraryPath(){ ifletlibraryPathString=NSSearchPathForDirectoriesInDomains(.libraryDirectory,.userDomainMask,true).first{ letpathURL=URL(fileURLWithPath:libraryPathString).appendingPathComponent("goods.sqlite") dbPath=pathURL.path } }
创建并连接数据库
funcopenDatabase()->OpaquePointer?{ vardb:OpaquePointer? ifsqlite3_open(dbPath,&db)==SQLITE_OK{ resultLabel.text="成功打开数据库,路径:\(dbPath)" returndb }else{ resultLabel.text="打开数据库失败" returnnil } }
通过上面的代码我们可以看到,首先声明了一个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的数据库了,接下来我们要做的就是创建一个表了。
创建表
代码
funccreateTable(){ letcreateTableString=""" CREATETABLEComputer( IdINTPRIMARYKEYNOTNULL, NameCHAR(255), WeightInt, PriceFloat); """ varcreateTableStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,createTableString,-1,&createTableStatement,nil)==SQLITE_OK{ //第二步 ifsqlite3_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编译为字节代码(bytecode)并返回一个statuscode,这个函数执行成功则表明database已经准备好了执行任意的SQLstatement(就是创建的SQL的字符串),该函数执行成功后即会执行sqlite3_step()。
- 第二步:sqlite3_step()用来执行编译完成的statementhandle(createTableStatement)并返回一个statuscode。
- 第三步:在你每一次的操作完成后你必须调用sqlite3_finalize()去删除你的statement以避免resourceleak。注意:一旦一个statement被finalized,你不应该再一次使用它。
插入一条数据
代码
funcinsertOneData(){ letinsertRowString="INSERTINTOComputer(Id,Name,Weight,Price)VALUES(?,?,?,?);" varinsertStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,insertRowString,-1,&insertStatement,nil)==SQLITE_OK{ letid: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) //第三步 ifsqlite3_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后调用。
- 第三步第四步同上
插入多条数据
代码
funcinsertMutipleData(){ letinsertRowString="INSERTINTOComputer(Id,Name,Weight,Price)VALUES(?,?,?,?);" varinsertStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,insertRowString,-1,&insertStatement,nil)==SQLITE_OK{ for(index,good)ingoodArr.enumerated(){ letid: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) //第三步 ifsqlite3_step(insertStatement)==SQLITE_DONE{ resultLabel.text="插入数据成功" }else{ resultLabel.text="插入数据失败" } //第四步 sqlite3_reset(insertStatement) } }else{ } //第五步 sqlite3_finalize(insertStatement) }
代码说明
- insertRowString同上。
- 第四步:调用sqlite3_reset()函数,以便下次循环再次执行insertStatement
- 第一步、第二步、第三步、第五步同上。
更新数据
代码
funcupdateData(){ letupdateString="UPDATEComputerSETName='changeComputer'WHEREId=2;" varupdateStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,updateString,-1,&updateStatement,nil)==SQLITE_OK{ //第二步 ifsqlite3_step(updateStatement)==SQLITE_DONE{ resultLabel.text="更新成功" }else{ } } //第三步 sqlite3_finalize(updateStatement) }
代码说明
- updateString:将Id==2的数据的Name字段改为changeComputer。
- sqlite3_prepare_v2():准备,sqlite3_step():执行更新statement,sqlite3_finalize():结束。
删除数据
代码
funcdeleteData(){ letdeleteString="DELETEFROMComputerWHEREId=2;" vardeleteStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,deleteString,-1,&deleteStatement,nil)==SQLITE_OK{ //第二步 ifsqlite3_step(deleteStatement)==SQLITE_DONE{ resultLabel.text="删除成功" } }else{ } //第三步 sqlite3_finalize(deleteStatement) }
代码说明
- deleteString:删除表中Id==2的数据。
- sqlite3_prepare_v2():准备,sqlite3_step():执行删除statement,sqlite3_finalize():结束。
查询一条数据
代码
funcqueryOneData(){ letqueryString="SELECT*FROMComputerWHEREId==2;" varqueryStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,queryString,-1,&queryStatement,nil)==SQLITE_OK{ //第二步 ifsqlite3_step(queryStatement)==SQLITE_ROW{ //第三步 letid=sqlite3_column_int(queryStatement,0) letqueryResultName=sqlite3_column_text(queryStatement,1) letname=String(cString:queryResultName!) letweight=sqlite3_column_int(queryStatement,2) letprice=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的数据。
- 第二步:注意此时要判断的statuscode为SQLITE_ROW,如果该判断为true则代表你查询的数据存在在表里。
- 第三步:sqlite3_column_int()函数是按照列数取数据,第一个参数是statement,第二个参数则是该字段是第几列(Id为表里的第一列,从0开始计算)。sqlite3_column_text()要略微复杂一点,他需要转换类型通过String(cString:queryResultName!)。
- 第一步、第四步同上
查询多条数据
代码
funcqueryAllData(){ letqueryString="SELECT*FROMComputer;" varqueryStatement:OpaquePointer? //第一步 ifsqlite3_prepare_v2(db,queryString,-1,&queryStatement,nil)==SQLITE_OK{ //第二步 while(sqlite3_step(queryStatement)==SQLITE_ROW){ //第三步 letid=sqlite3_column_int(queryStatement,0) letqueryResultName=sqlite3_column_text(queryStatement,1) letname=String(cString:queryResultName!) letweight=sqlite3_column_int(queryStatement,2) letprice=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~
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。