您的位置:首页 > 数据库

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,在内存中创建一个数据库,

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: