IOS数据持久化之Sqlite
2014-10-17 14:28
211 查看
上两篇博文分别说数据持久化之属性列表,数据持久化之NSKeyedArchiver,下面我们说说使用Sqlite数据库对数据进行持久化
Sqlite是一个轻量级的数据库,最初设计的目标是用于嵌入是系统中,它占用资源非常少,在嵌入式设备中,只需要几百K的内存就够了,
目前运用于Android、IOS、window phone等职能终端设备,IOS中也提供了SQLite操作的API,但是使用起来非常的不方便,在这里我们使用一个对SQLite API封装的开源类FMDB
FMDB是一个简洁、易用的库,下面我们对于Sqlite数据库的所有操作都将基于FMDB
首先下载FMDB,新建一个xcode项目,命名为DataSqliteDemo,我们把FMDB添加到新建的项目中,并且引入libsqlite3.dylib
FMDB说明:
FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
FMDB常用类:
FMDatabase : 一个单一的SQLite数据库,用于执行SQL语句。
FMResultSet :执行查询一个FMDatabase结果集,这个和android的Cursor类似。
FMDatabaseQueue :在多个线程来执行查询和更新时会使用这个类。
在使用的时候只需要发FMDB.h头文件引入即可
创建数据库
使用FMDatabase创建数据库,需要一个保存数据库的路径,路径可以使以下情况
1、一个指定的文件路径,如果文件不存在就创建它
2、一个空的字符串 @"",将在临时目录下面创建一个空的数据库,FMDatabase关闭的时候删除数据库
3、NULL,在内存中创建一个数据库,
FMDB执行更新说明,一个SQL语句,如果不是select,那么一律认为是update,执行更新使用executeUpdate,执行更新返回一个BOOL类型值,YES表示成功,NO表示失败
FMDB查询说明:执行查询使用executeQuery方法
FMDB事务使用begin/end transaction语句
FMDB多条SQL语句使用executeStatements:withResultBlock:
FMDB 数据提供的说明
在使用SQL语句进行操作时,应该使用标准的SQL语句,如下
INSERT INTO Member(Name,Age,Info) values(?,?,?)
或者可以使用参数的形式,如下:
INSERT INTO Member(Name,age,Info) values(:name,:age,:info);
FMDB执行SQL语句的时候应该使用如下方式:
NSDictionary *argsDict = [NSDictionary dictionaryWithObjectsAndKeys:@"My Name", @"name", nil];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];
或者
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has \" lots of ' bizarre \" quotes '"];
不应该是如下方式
[db executeUpdate:[NSString stringWithFormat:@"INSERT INTO myTable VALUES (%@)", @"this has \" lots of ' bizarre \" quotes '"]];
创建表:
插入数据:
修改数据:
查询数据:
删除数据:
事务:
多SQL语句执行:
安全地使用FMDatabaseQueue和线程
不要一次在多个线程中使用FMDatabase的单个实例。 在某一个线程中使用FMDatabase对象肯定是没问题的。只要别通过线程来共享变量,而且不要同时穿过多个线程。 否则会出现很严重的后果,应用崩溃,或得到异常
所以不要通过多线程使用实例和使用FMDatabase对象.
而是使用FMDatabaseQueue来完成相应的操作。 下面是使用方法:
示例代码下载
参考:http://www.tuicool.com/articles/YNzUR3
更详细的使用请查看官方文档:https://github.com/ccgus/fmdb#data-sanitization
Sqlite是一个轻量级的数据库,最初设计的目标是用于嵌入是系统中,它占用资源非常少,在嵌入式设备中,只需要几百K的内存就够了,
目前运用于Android、IOS、window phone等职能终端设备,IOS中也提供了SQLite操作的API,但是使用起来非常的不方便,在这里我们使用一个对SQLite API封装的开源类FMDB
FMDB是一个简洁、易用的库,下面我们对于Sqlite数据库的所有操作都将基于FMDB
首先下载FMDB,新建一个xcode项目,命名为DataSqliteDemo,我们把FMDB添加到新建的项目中,并且引入libsqlite3.dylib
FMDB说明:
FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
FMDB常用类:
FMDatabase : 一个单一的SQLite数据库,用于执行SQL语句。
FMResultSet :执行查询一个FMDatabase结果集,这个和android的Cursor类似。
FMDatabaseQueue :在多个线程来执行查询和更新时会使用这个类。
在使用的时候只需要发FMDB.h头文件引入即可
创建数据库
使用FMDatabase创建数据库,需要一个保存数据库的路径,路径可以使以下情况
1、一个指定的文件路径,如果文件不存在就创建它
2、一个空的字符串 @"",将在临时目录下面创建一个空的数据库,FMDatabase关闭的时候删除数据库
3、NULL,在内存中创建一个数据库,
#pragma mark 创建或者打开数据库 -(void)initFMDB{ NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [array objectAtIndex:0]; NSString *destpath = [path stringByAppendingPathComponent:@"Users.db"]; dbpath = destpath; db = [FMDatabase databaseWithPath:dbpath]; }
FMDB执行更新说明,一个SQL语句,如果不是select,那么一律认为是update,执行更新使用executeUpdate,执行更新返回一个BOOL类型值,YES表示成功,NO表示失败
FMDB查询说明:执行查询使用executeQuery方法
FMDB事务使用begin/end transaction语句
FMDB多条SQL语句使用executeStatements:withResultBlock:
FMDB 数据提供的说明
在使用SQL语句进行操作时,应该使用标准的SQL语句,如下
INSERT INTO Member(Name,Age,Info) values(?,?,?)
或者可以使用参数的形式,如下:
INSERT INTO Member(Name,age,Info) values(:name,:age,:info);
FMDB执行SQL语句的时候应该使用如下方式:
NSDictionary *argsDict = [NSDictionary dictionaryWithObjectsAndKeys:@"My Name", @"name", nil];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];
或者
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has \" lots of ' bizarre \" quotes '"];
不应该是如下方式
[db executeUpdate:[NSString stringWithFormat:@"INSERT INTO myTable VALUES (%@)", @"this has \" lots of ' bizarre \" quotes '"]];
创建表:
#pragma mark 创建表 -(void)BtnCreateTable:(id)sender{ if([db open]){ NSString *createTableSql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@' INTEGER PRIMARY KEY AUTOINCREMENT,'%@' VARCHAR(255) NOT NULL,'%@' INTEGER,'%@' TEXT,'%@' FLOAT DEFAULT 60,'%@' DATE DEFAULT CURRENT_DATE)",@"Member",@"ID",@"Name",@"Age",@"Info",@"Weight",@"CreateDate"]; if([db executeUpdate:createTableSql]){ NSLog(@"创建表成功"); }else{ NSLog(@"创建表失败"); } [db close]; } }
插入数据:
#pragma mark 插入数据 -(void)BtnInsert:(id)sender{ NSString *insertSql = @"INSERT INTO Member(Name,Age,Info,Weight) values(:name,:age,:info,:weight)"; if([db open]){ NSDictionary *paraDic =[NSDictionary dictionaryWithObjectsAndKeys:@"paul",@"name",@"20",@"age",@"add person",@"info",@"60",@"weight", nil]; if([db executeUpdate:insertSql withParameterDictionary:paraDic]){ NSLog(@"添加第一条数据成功"); }else{ NSLog(@"添加第一条数据失败"); } NSString *insertSql2 = @"INSERT INTO Member(Name,age,Info,Weight) values(?, ?, ? , ?)"; //if([db executeUpdate:insertSql2,@"Katt",[NSNumber numberWithInt:21],"Katt new",[NSNumber numberWithFloat:50]]){ if([db executeUpdate:insertSql2,@"Katt",@"21",@"Katt new",@"50"]){ NSLog(@"添加第二条数据成功"); }else{ NSLog(@"添加第二条数据失败"); } //FMDB不提倡使用下面的做法 NSString *insertSql3 = [NSString stringWithFormat:@"INSERT INTO Member(Name,age,Info,weight) values('%@',%@,'%@',%@)",@"angel",[NSNumber numberWithInteger:23],@"new angel",@"63.2"]; if([db executeUpdate:insertSql3]){ NSLog(@"添加第三条数据成功"); }else{ NSLog(@"添加第三条数据失败"); } [db close]; } }
修改数据:
#pragma mark 修改数据 -(void)BtnUpdate:(id)sender{ NSString *updateSql = @"UPDATE Member set Name = ? where ID = ?"; if([db open]){ if([db executeUpdate:updateSql,@"new name",[NSNumber numberWithInt:2]]){ NSLog(@"修改数据成功"); }else{ NSLog(@"修改数据失败"); } [db close]; } }
查询数据:
#pragma mark 查询 -(void)BtnSelect:(id)sender{ if([db open]){ NSString * querySql = @"select * from Member"; FMResultSet *result =[db executeQuery:querySql]; while ([result next]) { NSString * name = [result objectForColumnName:@"Name"]; int ID = [result intForColumn:@"ID"]; NSString *info =[ result objectForColumnName:@"info"]; NSLog(@"ID:%d,Name:%@,Info:%@",ID,name,info); } [db close]; } }
删除数据:
#pragma mark 删除 -(void)BtnDelete:(id)sender{ NSString * deleteSql = @"delete from Member where ID = :ID"; NSDictionary *paraDic =[NSDictionary dictionaryWithObjectsAndKeys:@"2",@"ID", nil]; if([db open]){ if([db executeUpdate:deleteSql withParameterDictionary:paraDic]){ NSLog(@"删除数据成功"); }else{ NSLog(@"删除数据失败"); } [db close]; } }
事务:
#pragma mark 事务 -(void)BtnTransaction:(id)sender{ if([db open]){ @try { [db beginTransaction]; NSString *insertSql = @"INSERT INTO Member(Name,Age,Info,Weight) values(:name,:age,:info,:weight)"; NSDictionary *paraDic =[NSDictionary dictionaryWithObjectsAndKeys:@"paul1",@"name",@"20",@"age",@"add person",@"info",@"60",@"weight", nil]; if([db executeUpdate:insertSql withParameterDictionary:paraDic]){ NSLog(@"添加第一条数据成功"); }else{ NSLog(@"添加第一条数据失败"); [db rollback]; return; } NSString *insertSql2 = @"INSERT INTO Member(Name,age,Info,Weight) values(?, ?, ? , ?)"; if([db executeUpdate:insertSql2,@"Katt2",@"21",@"Katt new",@"50"]){ NSLog(@"添加第二条数据成功"); }else{ NSLog(@"添加第二条数据失败"); [db rollback]; return; } NSLog(@"事务执行成功"); [db commit]; } @catch (NSException *exception) { NSLog(@"异常、事务回滚"); [db rollback]; } @finally { [db close]; } } }
多SQL语句执行:
#pragma mark 多SQL语句 -(void)BtnMultiSql:(id)sender{ NSString *multiSql = @"CREATE Table Member1(ID integer primary key autoincrement,Info text);Create Table Member2(ID integer primary key autoincrement,Name text);Create Table Member3(ID integer primary key autoincrement,remark text);insert into Member1(Info) values('abc');Insert into Member2(Name) values ('jack');insert into Member3(remark) values ('new member')"; NSString *multiquerySql = @"select * from Member1;select * from Member2;select * from Member"; if([db open]){ if([db executeStatements:multiSql]){ NSLog(@"执行多条SQL语句成功"); }else{ NSLog(@"执行多条SQL语句失败"); return; } BOOL success = [db executeStatements:multiquerySql withResultBlock:^int(NSDictionary *resultsDictionary) { NSLog(@"result:%@",resultsDictionary); return 0; }]; [db close]; } }
安全地使用FMDatabaseQueue和线程
不要一次在多个线程中使用FMDatabase的单个实例。 在某一个线程中使用FMDatabase对象肯定是没问题的。只要别通过线程来共享变量,而且不要同时穿过多个线程。 否则会出现很严重的后果,应用崩溃,或得到异常
所以不要通过多线程使用实例和使用FMDatabase对象.
而是使用FMDatabaseQueue来完成相应的操作。 下面是使用方法:
#pragma mark -(void)BtnMultiThread:(id)sender{ FMDatabaseQueue *queue =[FMDatabaseQueue databaseQueueWithPath:dbpath]; [queue inDatabase:^(FMDatabase *queuedb) { [queuedb executeUpdate:@"INSERT INTO Member1(Info) values(?)",@"Member info1"]; [queuedb executeUpdate:@"INSERT INTO Member2(Name) values(?)",@"Member2 Name"]; FMResultSet *rs =[queuedb executeQuery:@"select * from Member1"]; while ([rs next]) { NSLog(@"Info:%@",[rs objectForColumnName:@"Info"]); } }]; /* [queue inTransaction:^(FMDatabase *queuedb, BOOL *rollback) { }]; */ }
示例代码下载
参考:http://www.tuicool.com/articles/YNzUR3
更详细的使用请查看官方文档:https://github.com/ccgus/fmdb#data-sanitization
相关文章推荐
- ios数据持久化之数据库(SQLite)
- iOS数据持久化—SQLite常用的函数
- iOS 开发如果涉及数据和表的持久化,Core Data 比 SQLite 更好吗?
- 【转】IOS数据持久化三个方法:plist、sqlite3、Archiver
- ios开发学习笔记--数据持久化之数据库(SQLite.swift)
- iOS-数据持久化-SQlite3
- iOS.数据持久化.PersistenceLayer.SQLite
- iOS数据持久化—数据库SQLite模糊查询
- iOS数据持久化-sqlite3
- iOS 开发如果涉及数据和表的持久化,Core Data 比 SQLite 更好吗?
- iOS数据持久化——SQLite(数据库)
- ios开发之数据的持久化存储机制NSuserDefault、Plist、archiver、Sqlite、coreData
- iOS数据持久化—SQLite简单介绍
- IOS线程数据篇6之数据持久化plist、preference、NSKeyedArchiver(NSCoding)、Core Data、SQLite3
- ios数据持久化-属性列表NSUserDefaults、对象归档NSKeyedArchiver和NSKeyedUnarchive、嵌入式数据库(SQLite3)
- iOS学习之sqlite的创建数据库,表,插入查看数据
- iOS开发:使用SQLite3存储和读取数据
- iOS开发24:使用SQLite3存储和读取数据
- IOS持久化数据----(保存数据的一系列方法)