1.什么是FMDB:
- FMDB是iOS平臺的SQLite數(shù)據(jù)庫框架
- FMDB以O(shè)C的方式封裝了SQLite的C語言API
FMDB的優(yōu)點(diǎn):
- 使用起來更加面向?qū)ο螅∪チ撕芏嗦闊└氏簟⑷哂嗟腃語言代碼提供了多線程安全的數(shù)據(jù)庫操作方法,有效地防止數(shù)據(jù)混亂
FMDB的github地址:
2.核心類
FMDB有三個主要的類
- FMDatabase
- 一個FMDatabase對象就代表一個單獨(dú)的SQLite數(shù)據(jù)庫用來執(zhí)行SQL語句
-
FMResultSet
- 使用FMDatabase執(zhí)行查詢后的結(jié)果集
-
FMDatabaseQueue
- 用于在多線程中執(zhí)行多個查詢或更新牙言,它是線程安全的
3.通過指定SQLite數(shù)據(jù)庫文件路徑來創(chuàng)建FMDatabase對象
FMDatabase *db = [FMDatabase databaseWithPath:path];
if(![db open])
{
NSLog(@"數(shù)據(jù)庫打開失敼值谩!");
}
文件路徑有三種情況:
- 具體文件路徑
- 如果不存在會自動創(chuàng)建
- 空字符串@""
- 會在臨時目錄創(chuàng)建一個空的數(shù)據(jù)庫
- 當(dāng)FMDatabase連接關(guān)閉時庞钢,數(shù)據(jù)庫文件也被刪除
- nil
- 會創(chuàng)建一個內(nèi)存中臨時數(shù)據(jù)庫因谎,當(dāng)FMDatabase連接關(guān)閉時财岔,數(shù)據(jù)庫會被銷毀
4.執(zhí)行更新/執(zhí)行查詢
################## 更新方法 ################
在FMDB中河爹,除查詢以外的所有操作,都稱為“更新”,create夷恍、drop媳维、insert、update指黎、delete等使用executeUpdate:方法執(zhí)行更新
- (BOOL)executeUpdate:(NSString*)sql,...
- (BOOL)executeUpdateWithFormat:(NSString*)format,...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
n示例
[db executeUpdate:@"UPDATE t_student SET age = ?WHERE name = ?;", @20, @"Jack"]
-------------------------------------------------------------
################################## 查詢方法 ##################################
(FMResultSet *)executeQuery:(NSString*)sql,...
(FMResultSet *)executeQueryWithFormat:(NSString *)format,...
(FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
示例
//查詢數(shù)據(jù)
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];
//遍歷結(jié)果集
while([rs next])
{
NSString *name = [rs stringForColumn:@"name"];
int age = [rs intForColumn:@"age"];
double score = [rs doubleForColumn:@"score"];
}
5.FMDatabaseQueue
FMDatabase這個類是線程不安全的州丹,如果在多個線程中同時使用一個FMDatabase實(shí)例,會造成數(shù)據(jù)混亂等問題為了保證線程安全吓揪,F(xiàn)MDB提供方便快捷的FMDatabaseQueue類
FMDatabaseQueue的創(chuàng)建:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
使用事務(wù)
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next])
{
//執(zhí)行操作
}
}];
事務(wù)回滾
*rollback = YES;
01-FMDB基本使用
橋接文件
// Sqlite+Bridge.h
// 01-FMDB基本使用
// Created by ming on 16/04/16.
// Copyright ? 2016年 ming. All rights reserved.
#import "FMDB.h"
SQLiteManager
// SQLiteManager.swift
// 01-FMDB基本使用
// Created by ming on 16/04/16.
// Copyright ? 2016年 ming. All rights reserved.
import UIKit
class SQLiteManager: NSObject {
/// 單例
static let shareInstance: SQLiteManager = SQLiteManager()
override init() {
super.init()
openDB("demo.sqlite")
}
var db: FMDatabase?
func openDB(name: String)
{
// 1.拼接路徑
let path = name.documentDir()
// 2.創(chuàng)建數(shù)據(jù)庫對象
db = FMDatabase(path: path)
// 3.打開數(shù)據(jù)庫
// open()特點(diǎn): 如果數(shù)據(jù)庫文件不存在就創(chuàng)建一個新的, 如果存在就直接打開
if !db!.open()
{
print("打開數(shù)據(jù)庫失敗")
return
}
// 4.創(chuàng)建表
if !createTable()
{
print("創(chuàng)建數(shù)據(jù)庫失敗")
return
}
}
/**
創(chuàng)建表
*/
func createTable() ->Bool
{
// 1.編寫SQL語句
let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
"name TEXT, \n" +
"age INTEGER \n" +
");"
// 2.執(zhí)行SQL語句
// 注意: 在FMDB中, 除了查詢以外的操作都稱之為更新
return db!.executeUpdate(sql, withArgumentsInArray: nil)
}
}
ViewController
// ViewController.swift
// 01-FMDB基本使用
// Created by ming on 16/04/16.
// Copyright ? 2016年 ming. All rights reserved.
import UIKit
class ViewController: UIViewController {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("abc".documentDir())
// SQLiteManager.shareInstance.openDB("demo.sqlite")
/// DML
let sql = "INSERT INTO T_Person \n" +
"(name, age) \n" +
"VALUES \n" +
"(?, ?);"
// SQLiteManager.shareInstance.db?.executeUpdate(sql, withArgumentsInArray: nil)
SQLiteManager.shareInstance.db?.executeUpdate(sql, withArgumentsInArray: ["ls", 88])
/// 查詢語句
let sql2 = "SELECT id, name, age FROM T_Person;"
// 1.查詢數(shù)據(jù)庫
let result = SQLiteManager.shareInstance.db!.executeQuery(sql2, withArgumentsInArray: nil)
// 2.從結(jié)果集中取出數(shù)據(jù)
while result.next()
{
let id = result.intForColumn("id")
let name = result.stringForColumn("name")
let age = result.intForColumn("age")
print("\(id), \(name), \(age)")
}
}
}
02-FMDBQueue基本使用
import UIKit
class SQLiteManager: NSObject {
/// 單例
static let shareInstance: SQLiteManager = SQLiteManager()
override init() {
super.init()
openDB("demo.sqlite")
}
var dbQueue: FMDatabaseQueue?
func openDB(name: String) {
// 1.拼接路徑
let path = name.documentDir()
// 2.創(chuàng)建數(shù)據(jù)庫對象
dbQueue = FMDatabaseQueue(path: path)
// 3.創(chuàng)建表
createTable()
}
/**
創(chuàng)建表
*/
func createTable() {
// 1.編寫SQL語句
let sql = "CREATE TABLE IF NOT EXISTS T_Person( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT," +
"age INTEGER " +
");"
// 2.執(zhí)行SQL語句
dbQueue?.inDatabase({ (db) -> Void in
db.executeUpdate(sql, withArgumentsInArray: nil)
})
}
}
import UIKit
class ViewController: UIViewController {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("abc".documentDir())
// SQLiteManager.shareInstance.openDB("demo.sqlite")
/// DML
let sql = "INSERT INTO T_Person " +
"(name, age) " +
"VALUES " +
"(?, ?);"
// 只要使用inTransaction, 那么在inTransaction閉包中的所有代碼都是在事務(wù)中執(zhí)行的
SQLiteManager.shareInstance.dbQueue!.inTransaction { (db, rollback) -> Void in
for i in 0..<10
{
db.executeUpdate(sql, withArgumentsInArray: ["zs", 30])
// if i == 5
// {
// // OC中的寫法: *rollback = YES;
// // Swift2.x中的寫法: rollback.memory = true
// // Swift3.0中的寫法: rollback?.pointee = true
// rollback.memory = true
// }
}
}
}