一、概述
FMDB是iOS平台的SQLite数据库框架,它以OC的方式封装了SQLite的C语言API。FMDB的优点:
(1)使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码。
(2)对比苹果自带的Core Data框架,更加轻量级和灵活。
(3)提供了多线程安全的数据库操作方法,有效地防止数据混乱。
FMDB链接:https://github.com/ccgus/fmdb
将FMDB下载下来并且导入sqlite框架后添加到项目中就可以使用了。
FMDB中重要的类:
FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
FMResultSet:使用FMDatabase执行查询后的结果集
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的
二、FMDB的使用方法
首先要在用到的地方导入相关头文件:
1
|
#import "FMDB.h"
|
1、创建数据库
如果该位置没有此数据库文件将会建立一个新的数据库文件,如果已经有了,将会直接获得该数据库:
1
|
FMDatabase *
db
=
[
FMDatabase
databaseWithPath
:
dataBasePath
]
;
|
dataBasePath可以这样设定:
1
2
|
#define dataBasePath [[(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)) lastObject]stringByAppendingPathComponent:dataBaseName]
#define dataBaseName @"test.sqlite"
|
2、打开数据库
返回BOOL类型,代表是否成功:
1
|
[
db
open
]
|
3、关闭数据库
返回BOOL类型,代表是否成功:
1
|
[
db
close
]
|
4、创建新表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
创建表
*/
-
(
void
)
createTable
{
if
(
[
self
.
db
open
]
)
{
NSString *
sqlCreateTable
=
@
"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL)"
;
BOOL
res
=
[
self
.
db
executeStatements
:
sqlCreateTable
]
;
if
(
!
res
)
{
NSLog
(
@
"建表失败!"
)
;
}
else
{
NSLog
(
@
"建表成功!"
)
;
}
[
self
.
db
close
]
;
}
}
|
5、增加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/**
添加数据
*/
-
(
void
)
addData
:
(
NSString *
)
name
withAge
:
(
int
)
age
{
if
(
[
self
.
db
open
]
)
{
NSString *
sql
=
@
"INSERT INTO t_student (name, age) VALUES (?,?);"
;
BOOL
res
=
[
self
.
db
executeUpdate
:
sql
,
name
,
@
(
age
)
]
;
if
(
!
res
)
{
NSLog
(
@
"添加数据失败!"
)
;
}
else
{
NSLog
(
@
"添加数据成功!"
)
;
}
[
self
.
db
close
]
;
}
}
|
6、删除数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
删除数据
*/
-
(
void
)
delData
:
(
NSString *
)
name
{
if
(
[
self
.
db
open
]
)
{
NSString *
sql
=
@
"DELETE FROM t_student WHERE name = ?"
;
BOOL
res
=
[
self
.
db
executeUpdate
:
sql
,
name
]
;
if
(
!
res
)
{
NSLog
(
@
"删除数据失败!"
)
;
}
else
{
NSLog
(
@
"删除数据成功!"
)
;
}
[
self
.
db
close
]
;
}
}
|
7、修改数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/**
修改数据
*/
-
(
void
)
updateData
:
(
NSString *
)
name
{
if
(
[
self
.
db
open
]
)
{
NSString *
sql
=
@
"UPDATE t_student SET name = ?"
;
BOOL
res
=
[
self
.
db
executeUpdate
:
sql
,
name
]
;
if
(
!
res
)
{
NSLog
(
@
"修改数据失败!"
)
;
}
else
{
NSLog
(
@
"修改数据成功!"
)
;
}
[
self
.
db
close
]
;
}
}
|
8、查询数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/**
查询数据
*/
-
(
void
)
queryData
{
if
(
[
self
.
db
open
]
)
{
//返回数据库中第一条满足条件的结果
NSString *
sql
=
@
"SELECT * FROM t_student"
;
//返回全部查询结果
FMResultSet *
resultSet
=
[
self
.
db
executeQuery
:
sql
]
;
while
(
[
resultSet
next
]
)
{
int
idNum
=
[
resultSet
intForColumn
:
@
"id"
]
;
NSString *
name
=
[
resultSet
objectForColumnName
:
@
"name"
]
;
int
age
=
[
resultSet
intForColumn
:
@
"age"
]
;
NSLog
(
@
"id=%i ,name=%@, age=%i"
,
idNum
,
name
,
age
)
;
}
[
resultSet
close
]
;
[
self
.
db
close
]
;
}
}
|
要特别注意上面用的占位符为“?”而不是“%@”。
三、FMDatabaseQueue
FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题。为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类。
1、FMDatabaseQueue的创建与数据库操作
1
2
3
4
5
6
7
8
9
10
11
12
13
|
FMDatabaseQueue *
queue
=
[
FMDatabaseQueue
databaseQueueWithPath
:
path
]
;
[
queue
inDatabase
:
^
(
FMDatabase *
db
)
{
//从这个block中直接获得打开的数据库实例
[
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
]
)
{
// …
}
}
]
;
|
2、FMDatabaseQueue使用事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[
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"
]
;
if
(发现情况不对
)
{
*
rollback
=
YES
//回滚事务
}
FMResultSet *
rs
=
[
db
executeQuery
:
@
"select * from t_student"
]
;
while
(
[
rs
next
]
)
{
// …
}
}
]
;
|
当然也可以使用如下方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[
self
.
queue
inDatabase
:
^
(
FMDatabase *
db
)
{
// 开启事务
[
db
executeUpdate
:
@
"begin transaction;"
]
;
//等价于[db beginTransaction];
[
db
executeUpdate
:
@
"update t_student set age = ? where name = ?;"
,
@
20
,
@
"jack"
]
;
[
db
executeUpdate
:
@
"update t_student set age = ? where name = ?;"
,
@
20
,
@
"jack"
]
;
if
(发现情况不对
)
{
// 回滚事务
[
db
executeUpdate
:
@
"rollback transaction;"
]
;
//等价于[db rollback];
}
[
db
executeUpdate
:
@
"update t_student set age = ? where name = ?;"
,
@
20
,
@
"jack"
]
;
// 提交事务
[
db
executeUpdate
:
@
"commit transaction;"
]
;
//等价于[db commit];
}
]
;
|