读写应用程序数据-SQLite3
SQLite3是嵌入到ios中的关系型数据库。对存储大规模的数据非常实用,使得不必将每个对象加到内存中。
支持NULL、INTEGER、REAL(浮点数字)、TEXT(字符串和文本)、BLOB(二进制对象)数据类型。
1、通过Firefox中的SQLite Manager组件创建一个数据库文件,并在其中创建创建一个Table,添加相关的参数。
2、将创建好的文件推到Xcode项目中,并在Link Binary With Libraries中添加libsqlite3.dylib依赖库。
3、新建一个C语言类型文件,对话框会自动添加桥接文件,在文件中添加语句#import<sqlite3.h>。
4、然后创建一个DataBaseOperations.swift文件来管理数据库。
在DataBaseOperation.swift文件中,申明一个数据库指针。
//不透明指针,对应C语言里面的void *,这里指sqlite3指针
private var db:COpaquePointer = nil
创建一个初始化方法,在初始化方法中执行打开数据库操作。
//初始化方法打开数据库
required init(dbPath:String)
{
print("db path:" + dbPath) //String类的路径,转换成cString
let cpath = dbPath.cStringUsingEncoding(NSUTF8StringEncoding) //打开数据库
let error = sqlite3_open(cpath!, &db) //数据库打开失败处理
if error != SQLITE_OK {
sqlite3_close(db)
}
}
deinit{
self.colseDb()
}
//关闭数据库
func colseDb(){
sqlite3_close(db)
}
//代码创建表
func createTable() -> Bool{ //sql语句
let sql = "CREATE TABLE UserTable(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username TEXT NOT NULL, password TEXT NOT NULL, email TEXT, age INTEGER)" //执行sql语句
let execResult = sqlite3_exec(db, sql.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil); //判断是否执行成功
if (execResult != SQLITE_OK) {
return false
} return true
}
//插入一条信息
func addUser(user: Person) -> Bool
{
//sql语句
let sql = "INSERT INTO UserTable (username, password, email, age) VALUES (?, ?, ?, ?);";
//sql语句转换成cString类型 let cSql = sql.cStringUsingEncoding(NSUTF8StringEncoding) //sqlite3_stmt 指针
var stmt:COpaquePointer = nil //1.编译sql
let prepare_result = sqlite3_prepare_v2(self.db, cSql!, -, &stmt, nil) //判断如果失败,获取失败信息
if prepare_result != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to prepare SQL: \(sql), Error: \(error)"
print(msg)
self.alert(msg)
}
return false
} //2.bind 绑定参数
//第2个参数:索引从1开始
//最后一个参数为函数指针
sqlite3_bind_text(stmt, , user.name!.cStringUsingEncoding(NSUTF8StringEncoding)!, -, nil);
sqlite3_bind_text(stmt, , user.password!.cStringUsingEncoding(NSUTF8StringEncoding)!, -, nil);
sqlite3_bind_text(stmt, , user.email!.cStringUsingEncoding(NSUTF8StringEncoding)!, -, nil);
sqlite3_bind_int(stmt, , CInt(user.age!)); //3.step执行
let step_result = sqlite3_step(stmt) //判断执行结果,如果失败,获取失败信息
if step_result != SQLITE_OK && step_result != SQLITE_DONE {
sqlite3_finalize(stmt)
if let err = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to execute SQL: \(sql), Error: \(err)"
print(msg)
self.alert(msg)
}
return false
} //4.finalize
sqlite3_finalize(stmt); return true
}
//查询
func readAllUsers() -> [Person]{ //声明一个Person对象数组(查询的信息会添加到该数组)
var usersArr = [Person]() //查询sql语句
let sql = "SELECT * FROM UserTable;"; //sqlite3_stmt 指针
var stmt:COpaquePointer = nil
let cSql = sql.cStringUsingEncoding(NSUTF8StringEncoding) //1.编译sql
let prepare_result = sqlite3_prepare_v2(self.db, cSql!, -, &stmt, nil)
if prepare_result != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to prepare SQL: \(sql), Error: \(error)"
print(msg)
self.alert(msg)
}
return usersArr
} //2.step
while (sqlite3_step(stmt) == SQLITE_ROW) {
let user = Person() //循环 从数据库获取数据,添加到数组中
let cName = UnsafePointer<CChar>(sqlite3_column_text(stmt, ))
let cPwd = UnsafePointer<CChar>(sqlite3_column_text(stmt, ))
let cEmail = UnsafePointer<CChar>(sqlite3_column_text(stmt, ))
let cAge = sqlite3_column_int(stmt, ) user.name = String.fromCString(cName)
user.password = String.fromCString(cPwd)
user.email = String.fromCString(cEmail)
user.age = Int(cAge) usersArr += [user]
} //3.finalize
sqlite3_finalize(stmt); return usersArr
}
//更新一条信息
func updateUser(name: String , toName:String) -> Bool
{
//更新sql语句
let sql = "update UserTable set username = '\(toName)' where username = '\(name)'"; //sqlite3_stmt 指针
var stmt:COpaquePointer = nil
let cSql = sql.cStringUsingEncoding(NSUTF8StringEncoding) //1.编译sql
let prepare_result = sqlite3_prepare_v2(self.db, cSql!, -, &stmt, nil) //判断如果失败,获取失败信息
if prepare_result != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to prepare SQL: \(sql), Error: \(error)"
print(msg)
self.alert(msg)
}
return false
} //2.step执行
let step_result = sqlite3_step(stmt) //判断执行结果,如果失败,获取失败信息
if step_result != SQLITE_OK && step_result != SQLITE_DONE {
sqlite3_finalize(stmt)
if let err = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to execute SQL: \(sql), Error: \(err)"
print(msg)
self.alert(msg)
}
return false
} //4.finalize
sqlite3_finalize(stmt); return true
}
//删除一条信息
func deleteUser(username: String) -> Bool
{
//删除sql语句
let sql = "delete from UserTable where username = '\(username)'"; //sqlite3_stmt 指针
var stmt:COpaquePointer = nil
let cSql = sql.cStringUsingEncoding(NSUTF8StringEncoding) //1.编译sql
let prepare_result = sqlite3_prepare_v2(self.db, cSql!, -, &stmt, nil) //判断如果失败,获取失败信息
if prepare_result != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to prepare SQL: \(sql), Error: \(error)"
print(msg)
self.alert(msg)
}
return false
} //3.step执行
let step_result = sqlite3_step(stmt) //判断执行结果,如果失败,获取失败信息
if step_result != SQLITE_OK && step_result != SQLITE_DONE {
sqlite3_finalize(stmt)
if let err = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to execute SQL: \(sql), Error: \(err)"
print(msg)
self.alert(msg)
}
return false
} //4.finalize
sqlite3_finalize(stmt); return true
}
//定义一个报警器
func alert(msg:String) {
dispatch_async(dispatch_get_main_queue()) {
let alert = UIAlertView(title: "SQLiteDB", message:msg, delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
因为工程数据库文件打包之后,会在NSBundle.mainBundle()路径下,该路径是只读的,不允许修改,所以必须把该路径下的数据库拷贝一份到Documents路径下,以后整个工程都将操作Documents路径下的数据库。
在ViewController中,添加一下代码。
//声明一个Documents下的路径
let dbPath = NSHomeDirectory() + "/Documents/RWDataTest.sqlite" //判断数据库文件是否存在
if !NSFileManager.defaultManager().fileExistsAtPath(dbPath)
{
//获取安装包内数据库路径
let bundleDBPath = NSBundle.mainBundle().pathForResource("RWDataTest", ofType: "sqlite")! //将安装包内数据库拷贝到Documents目录下
do
{
try NSFileManager.defaultManager().copyItemAtPath(bundleDBPath, toPath: dbPath)
}
catch let error as NSError {
print(error)//如果创建失败,error 会返回错误信息
}
}
//打开数据库
let dbOperation = DatabaseOperations(dbPath: dbPath) //添加一张表
dbOperation.createTable(); //插入一条信息, 通过Person对象来传值
let person:Person = Person(name: "刘明洋", pwd: "liumingyang", email: "liumingyang@leadingdo.com", age: ) dbOperation.addUser(person) //查询
let personArray:[Person] = dbOperation.readAllUsers()
print("共搜索到:\(personArray.count) 条数据" ) //更新
dbOperation.updateUser("刘明洋", toName: "刘蕙通") //删除
dbOperation.deleteUser("刘蕙通") //关闭数据库
dbOperation.colseDb()
读写应用程序数据-SQLite3的更多相关文章
- 读写应用程序数据-NSUserDefault、对象归档(NSKeyedArchiver)、文件操作
ios中数据持久化存储方式一般有5种:NSUserDefault.对象归档(NSKeyedArchiver).文件操作.数据库存储(SQLite3).CoreData. 1.NSUserDefault ...
- 读写应用程序数据-CoreData
coreData数据最终的存储类型可以是:SQLite数据库.XML.二进制.内存里.自定义的数据类型. 和SQLite区别:只能取出整个实体记录,然后分解,之后才能得到实体的某个属性. 1.创建工程 ...
- C# 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC
本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 官方 ...
- python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据
本文将使用一个gitHub开源的组件技术来读写三菱的plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...
- java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC
本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...
- C#读写西门子PLC数据
C#读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC 本文将使用一个gitHub开源的组件技术来读写西门子plc数 ...
- C#读写三菱PLC数据 使用TCP/IP 协议
本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...
- 由于检索用户的本地应用程序数据路径时出错,导致无法生成 SQL Server 的用户实例
/”应用程序中的服务器错误. 由于检索用户的本地应用程序数据路径时出错,导致无法生成 SQL Server 的用户实例.请确保该用户在此计算机上有本地用户配置文件.该连接将关闭. 堆栈跟踪: [Sql ...
- 微信小程序数据请求方法wx.request小测试
微信小程序数据请求方法 wx.request wxml文件: <view> <textarea value="{{textdata}}"/> </vi ...
随机推荐
- Android 在AlertDialog里添加布局控件
android里很多时候需要在弹出的AlertDialog里有自己的控件,填写信息,比如弹出一个登陆对话框 那么首先你就要创建这么一个布局的inputphonenum.xml文件了 <?xml ...
- OpenCV学习笔记:矩阵的掩码操作
矩阵的掩码操作很简单.其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值.掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响.从数学观点看,我们用自己设置的权值,对像素邻 ...
- FRM-40401 No changes to save error
FAQ: I have updated a table from the form and written a update statement in the when-button-pressed ...
- Android开发UI之去掉title bar
去掉屏幕上的title bar有3个方法: 1.java代码实现: @Override publicvoid onCreate(Bundle savedInstanceState) { super.o ...
- EasyUI中datagrid的行编辑模式中,找到特定的Editor,并为其添加事件
有时候在行编辑的时候,一个编辑框的值要根据其它编辑框的值进行变化,那么可以通过在开启编辑时,找到特定的Editor,为其添加事件 // 绑定事件, index为当前编辑行 var editors = ...
- (转载)CentOS: 开放80、22、3306端口操作
(转载)http://blog.sina.com.cn/s/blog_3eba8f1c0100tsox.html #/sbin/iptables -I INPUT -p tcp --dport 80 ...
- [BILL WEI]SQL 如何将查询到的列作为表名去查询数据
我们在做sql查询的时候,有时候需要将查询的列作为表名,去引用,然后再次查询 declare @table_name varchar(20) select @table_name=table_name ...
- HDOJ-ACM1012(JAVA)
这道题很简单,主要是弄懂题意和注意输出: 输出的完整结果如下: n e - ----------- 0 1 1 2 2 2.5 3 2.666666667 4 2.708333333 5 2.7166 ...
- CF29D - Ant on the Tree(DFS)
题目大意 给定一棵树,要求你按给定的叶子节点顺序对整棵树进行遍历,并且恰好经过2*n-1个点,输出任意一条符合要求的路径 题解 每次从叶子节点开始遍历到上一个叶子节点就OK了, 这个就是符合要求的路径 ...
- ios 免书籍入门站点
http://www.raywenderlich.com/tutorials http://www.raywenderlich.com/ios-tutorials http://web.stanfor ...