SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库。iOS SDK很早就支持了SQLite,在使用时,只须要加入 libsqlite3.dylib 依赖以及引入 sqlite3.h 头文件便可。可是,原生的SQLite API在使用上至关不友好,在使用时,很是不便。因而,开源社区中就出现了一系列将SQLite API进行封装的库,而FMDB (https://github.com/ccgus/fmdb) 则是开源社区中的优秀者。php
FMDB在使用上至关方便。如下是一个简单的例子:html
1
2 3 4 5 6 7 8 9 10 11 |
NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString* dbpath = [docsdir stringByAppendingPathComponent:@"user.sqlite"]; FMDatabase* db = [FMDatabase databaseWithPath:dbpath]; [db open]; FMResultSet *rs = [db executeQuery:@"select * from people"]; while ([rs next]) { NSLog(@"%@ %@", [rs stringForColumn:@"firstname"], [rs stringForColumn:@"lastname"]); } [db close]; |
能够看到,使用FMDB后的数据库代码清晰明了,比原生的API优雅多了。另外,FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。mysql
该使用说明主要翻译自fmdb的github项目说明文档: https://github.com/ccgus/fmdbgit
首先将FMDB从github上clone下来,而后将如下文件copy到你的工程中:github
1
2 3 4 5 6 7 8 9 10 |
FMDatabase.h FMDatabase.m FMDatabaseAdditions.h FMDatabaseAdditions.m FMDatabasePool.h FMDatabasePool.m FMDatabaseQueue.h FMDatabaseQueue.m FMResultSet.h FMResultSet.m |
创建数据库只须要以下一行便可,当该文件不存在时,fmdb会本身建立一个。若是你传入的参数是空串:@”” ,则fmdb会在临时文件目录下建立这个数据库,若是你传入的参数是 NULL,则它会创建一个在内存中的数据库。sql
1
|
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; |
使用以下语句,若是打开失败,多是权限不足或者资源不足。一般打开完操做操做后,须要调用close方法来关闭数据库。数据库
1
2 3 4 5 6 7 8 |
if (![db open]) { // error return; } // some operation // ... [db close]; |
除了Select操做以外,其它的都是更新操做。更新操做使用以下方法,若是有错误,能够用error参数中得到。安全
1
|
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:] |
查询操做示例以下。注意:即便操做结果只有一行,也须要先调用FMResultSet的next方法。多线程
1
2 3 4 5 6 7 8 9 |
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"]; while ([s next]) { //retrieve values for each record } FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"]; if ([s next]) { int totalCount = [s intForColumnIndex:0]; } |
FMDB提供以下多个方法来获取不一样类型的数据:闭包
1
2 3 4 5 6 7 8 9 10 11 |
intForColumn: longForColumn: longLongIntForColumn: boolForColumn: doubleForColumn: stringForColumn: dateForColumn: dataForColumn: dataNoCopyForColumn: UTF8StringForColumnIndex: objectForColumn: |
一般状况下,你并不须要关闭FMResultSet,由于相关的数据库关闭时,FMResultSet也会被自动关闭。
一般状况下,你能够按照标准的SQL语句,用?表示执行语句的参数,如:
1
|
INSERT INTO myTable VALUES (?, ?, ?) |
而后,能够咱们能够调用executeUpdate方法来将?所指代的具体参数传入,一般是用变长参数来传递进去的,以下:
1
2 |
NSString *sql = @"insert into User (name, password) values (?, ?)"; [db executeUpdate:sql, user.name, user.password]; |
这里须要注意的是,参数必须是NSObject的子类,因此象int,double,bool这种基本类型,须要封装成对应的包装类才行,以下所示:
1
2 3 4 |
// 错误,42不能做为参数 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42]; // 正确,将42封装成 NSNumber 类 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]]; |
若是咱们的app须要多线程操做数据库,那么就须要使用FMDatabaseQueue来保证线程安全了。切记不能在多个线程中共同一个FMDatabase对象而且在多个线程中同时使用,这个类自己不是线程安全的,这样使用会形成数据混乱等问题。
使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,而后就能够将一个闭包(block)传入inDatabase方法中。在闭包中操做数据库,而不直接参与FMDatabase的管理。
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 27 28 |
// 建立,最好放在一个单例的类中 FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; // 使用 [queue inDatabase:^(FMDatabase *db) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; FMResultSet *rs = [db executeQuery:@"select * from foo"]; while ([rs next]) { // … } }]; // 若是要支持事务 [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; if (whoopsSomethingWrongHappened) { *rollback = YES; return; } // etc… [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; }]; |
为了查看Sqlite中的数据,一个好的图形化界面的数据库管理程序是必不可少的。mysql有phpMyAdmin,那么sqlite呢?
我主要使用的是Firefox的一个名为SQLite Manager的插件,安装此插件后,能够直接打开后缀名为sqlite的数据库文件。SQLite Manager提供一个图形化的界面来执行数据查询或更改操做。以下图所示:
FMDB将SQLite API进行了很友好的封装,使用上很是方便,对于那些使用纯Sqlite API来进行数据库操做的app,能够考虑将其迁移到基于FMDB上,这对于之后数据库相关功能的开发维护,能够提升很多效率。