原生SQLite-数据库操作
基于SQLite自身的诸多优点,在IOS开发中它是不二的选择; 除了会使用框架,接下来我们来看一下原生SQLite是如何操作的.
接下来就进入数据库了: 数据库是独立的文件,每个APP都有独立的沙盒,数据库就存在APP的沙盒中. 应用程序访问时直接访问这个唯一的数据库文件,因此在实际开发中我们操作这个数据库文件时采用单例;单例的好处: 一个APP有多个页面,可能都会涉及到数据库访问,为了方便管理,因此采用单例.
// 单例
static let sharedManager = SQLiteManager()
// 全局的数据库访问句柄
// C语言中没有对象,如果想要实现类似面向对象的功能,是通过结构体实现的
// db为指向结构体的指针
var db: COpaquePointer = nil
// 打开数据库
// 目的: 数据库是一个独立的文件,在程序启动时,打开一次,提供存储数据的空间!
// 参数: 数据库名字
func openDB(dbName: String) {
var path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]
// 数据库在沙盒中的路径
path = (path as NSString).stringByAppendingPathComponent(dbName)
// 参数1:(filename: UnsafePointer<Int8>) 文件名 Int8 -> uint8 -> Char -> Byte 纯 C 语言格式的路径
// 但是,从 Xcode 7.0 beta 5 之后,可以使用 String (Swift)
// 参数2: (ppDb: UnsafeMutablePointer<COpaquePointer>)`全局`数据库访问`句柄`(指针) -> 后续所有数据库的操作,都基于这个句柄
// 这个函数执行完了来改变db的地址,因此上面定义用var
// 返回值: SQLite 的函数,绝大多数成功都是用 SQLITE_OK 判断
// 细节: 如果数据库不存在,会新建再打开,如果已经存在,会直接打开!
if sqlite3_open(path,&db) != SQLITE_OK {
print("数据库打开失败")
return
}
print("数据库打开成功")
// 打开成功后,创建数据表,函数在后面
createTable1()
}
func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// `持久化`连接
// 在开发本地数据库的时候,通常只会打开数据库,不会关闭数据库
// 一旦打开之后,后续只需要做读写操作即可,效率更高!
// 分享: 对应的网络有长连接,但是做网络开发,数据库访问结束后,是必须关闭,并且断开连接(切断的目的: 把服务器的链接资源释放,保证一台服务器为更多地用户响应)!
SQLiteManager.sharedManager.openDB("my.db")
return true
}
func execSQL(sql: String) -> Bool {
// 参数1: 全局数据库句柄
// 参数2: sql 语句的 C 语言的字符串,swift 可以使用 String
// 参数3: callback 回调-执行 SQL 完成之后,调用的 C 语言的函数指针,通常传入 nil
// 参数4: 参数3的参数地址,通常传入 nil
// 参数5: 错误信息的地址,通常传入 nil,有其他方式获取错误提示
// 返回值: SQLITE_OK
*/
return sqlite3_exec(db,sql,nil,nil) == SQLITE_OK
}
private func createTable1() -> Bool {
// 1. 准备 SQL
let sql = "CREATE TABLE n" +
"IF NOT EXISTS 'T_Person' ( n" +
"'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,n" +
"'name' TEXT,n" +
"'age' INTEGER,n" +
"'height' REAL,n" +
"'title' TEXTn" +
");"
print(sql)
// 2. 执行 SQL
return execSQL(sql)
}
数据库开发技巧分享:
-- 创建个人数据表
CREATE TABLE IF NOT EXISTS "T_Person" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"name" TEXT,"age" INTEGER,"height" REAL );
-- 创建图书数据表
CREATE TABLE IF NOT EXISTS "T_Book" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"bookName" TEXT );
读取db.sql,创建数据表 private func createTable2() -> Bool {
// 1. 准备 sql - 读取文件
let path = NSBundle.mainBundle().pathForResource("db.sql",ofType: nil)!
let sql = try! String(contentsOfFile: path)
// 2. 执行sql
return execSQL(sql)
执行结果: 在数据库中两个表都创建成功(个人/图书) if createTable1() {
print("创表成功")
} else {
print("创表失败")
}
// Person身上的属性
var id: Int64 = 0
var name: String?
var age = 0
var height: Double = 0
// person的构造方法
init(dict: [String: AnyObject]) {
super.init()
setValuesForKeysWithDictionary(dict)
}
// 重写description方法
override var description: String {
let keys = ["id","name","age","height"]
// 下面两种方式等价
return "(dictionaryWithValuesForKeys(keys))"
// return dictionaryWithValuesForKeys(keys).description
}
// MARK: - 数据库操作 目标1: 插入数据
/// 执行 SQL 插入数据,返回 自动增长的 id
func execInsert(sql: String) -> Int64 {
// 1. 执行 SQL,如果失败,返回 -1
if !execSQL(sql) {
return -1
}
// 2. 如果成功,返回最后插入记录的 id,自动增长的 id
return Int64(sqlite3_last_insert_rowid(db))
}
/// 将当前对象插入到数据库
func insertPerson() -> Bool {
// 0. 判断 name 是否为nil
guard let name = name else {
print("name 不能为 nil")
return false
}
// 1. 准备 SQL
let sql = "INSERT INTO T_Person (name,age,height) VALUES n" +
"('(name)',(age),(height));"
// 2. 执行 SQL
id = SQLiteManager.sharedManager.execInsert(sql)
// id > 0 表示数据插入成功!
return id > 0
}
private func demoInsert() {
let p = Person(dict: ["name": "zhang","age": 19,"height": 1.6])
if p.insertPerson() {
print("插入成功 (p)")
} else {
print("插入失败")
}
}
目标2: 更新数据
/// 执行 SQL 更新 / 删除 数据,返回更新的数据行数
func execUpdate(sql: String) -> Int {
// 1. 执行 SQL,如果失败,返回 -1
if !execSQL(sql) {
return -1
}
// 2. 如果 更新 / 删除 成功,返回最后`修改/删除`的数据行数
return Int(sqlite3_changes(db))
}
/// 使用当前对象的信息更新数据库
func updatePerson() -> Bool {
// 0. 判断 name 是否为nil
guard let name = name else {
print("name 不能为 nil")
return false
}
if id <= 0 {
print("id 不正确,person和数据库没有关系")
return false
}
// 1. 准备 SQL
let sql = "UPDATE T_Person set name = '(name)',age = (age),height = (height) n" +
"WHERE id = (id);"
// 2. 执行 SQL - 如果修改的行数 > 0 ,表示修改成功
return SQLiteManager.sharedManager.execUpdate(sql) > 0
}
private func demoUpdate() {
let p = Person(dict: ["id": 1,"name": "张三","age": 190,"height": 16])
if p.updatePerson() {
print("更新成功 (p)")
} else {
print("更新失败")
}
目标3: 删除数据
// 删除当前对象在数据库中的记录
func deletePerson() -> Bool {
if id <= 0 {
print("id 不正确,person和数据库没有关系")
return false
}
// 1. 准备 sql
let sql = "DELETE FROM T_Person WHERE id = (id);"
// 2. 执行 sql
return SQLiteManager.sharedManager.execUpdate(sql) > 0
}
private func demoDelete() {
let p = Person(dict: ["id": 2,"height": 16])
if p.deletePerson() {
print("删除成功")
} else {
print("删除失败")
}
} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Oracle内存全面分析 2
- ruby-on-rails – Rails has_many通过where条件
- react-native – 在React Native中解析src dir以进行导入
- ADSP-BF531的SPI FLASH BOOT
- c# – WebActivatorEx在Application Start上导致ArgumentEx
- swf自动适应大小的变化,设置swf的全屏,支持退出全屏的esc
- c – 如何编写UTF-8安全码?
- ruby / rails相当于javascript decodeURIComponent?
- 依赖在代码中的几种表现形式
- ruby – 将帖子数据传递给Sinatra中的其他页面