前面有两篇《【iOS】数据库FMDB的使用》介绍了FMDB和一篇介绍了Core Data的使用《【iOS】数据库Core Data的使用》。
这篇将要介绍SQLite3的使用。FMDB是SQLite3的一个封装,所以使用起来和两者的基本操作流程是一样的。
SQLite3在存储和检索大量数据方面非常有效。它能够对数据进行复杂的聚合,与使用对象执行这些操作相比,获得结的速度更快。SQLite3可以不需要将所有对象加载到内存中就可以获取这些信息。
SQLite3使用SQL(Structured Query Language,结构化查询语言)。SQL是与关系数据库交互的标准语言。SQLite3也是一种关系数据库。
#define FILE_NAME @"SQLtest" #define TABLE_NAME @"SQLtest" @interface ViewController (){ sqlite3 *dataBase; } @property (nonatomic,strong)NSArray *nameArray; @end
新建一个项目;
添加依赖文件libsqlite3.dylib(Xcode7下面是libsqlite3.tbd);
项目在添加头文件#import<sqlite3.h>
使用SQLite3之前,必须先要打开数据库。这点和FMDB的操作是一致的。
数据库的打开和关闭操作:
sqlite3_open()
sqlite3_close()
/** * 根据文件名获取文件路径 * * @param fileName 文件名 * * @return 返回文件路径 */ - (NSString *)getFilePath:(NSString *)fileName{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documetsDirectory = [paths objectAtIndex:0]; return [documetsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite",fileName]]; } /** * 打开数据库 * * @return YES:打开成功 NO:打开失败 */ - (BOOL)openDataBase{ int result = sqlite3_open([self getFilePath:FILE_NAME].UTF8String, &dataBase); if (result == SQLITE_OK) { NSLog(@"数据库打开成功"); return YES; } else{ NSLog(@"数据库打开失败"); return NO; } } /** * 关闭数据库 */ - (void)closeDataBase{ sqlite3_close(dataBase); }
在打开数据库中的结果等于SQLITE_OK表示数据库打开成功,否则打开失败。SQLITE_OK是一个系统的宏定义。需要注意的是,在使用文件路径的时候,需要将OC字符串转为C字符串,好在OC给我们提供了这样的一个方法UTF8String。下面所涉及到的SQLite3的一些操作里面的OC字符串也都需要转为C字符串处理。
/** * 数据库中创建表 */ - (void)creatDataBase{ if (![self openDataBase]) { return; } NSString *creatSQL = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (rowid INTEGER PRIMARY KEY AUTOINCREMENT, name text,age text,address text)",TABLE_NAME]; char *errorMsg; int result = sqlite3_exec(dataBase, creatSQL.UTF8String, NULL, NULL, &errorMsg); if (result == SQLITE_OK) { [self closeDataBase]; NSLog(@"表单:%@创建成功",TABLE_NAME); } else{ NSLog(@"表单:%@创建失败:%s",TABLE_NAME,errorMsg); } }
这里的学生模型还是前面介绍FMDB里面的学生模型。
/** * 以学生模型插入数据库 * * @param student 学生数据模型 */ - (void)insterStudent:(Student *)student{ if (![self openDataBase]) { return; } NSString *insterSQL = [NSString stringWithFormat:@"INSERT OR REPLACE INTO %@ (name,age,address) VALUES (?,?,?)",TABLE_NAME]; char *errorMsg; sqlite3_stmt *stmt; if (sqlite3_prepare_v2(dataBase, insterSQL.UTF8String, -1, &stmt, nil) == SQLITE_OK) { sqlite3_bind_text(stmt, 1, student.name.UTF8String, -1, nil); sqlite3_bind_text(stmt, 2, student.age.UTF8String, -1, nil); sqlite3_bind_text(stmt, 3, student.address.UTF8String, -1, nil); } if (sqlite3_step(stmt) != SQLITE_DONE) { NSLog(@"数据插入失败:%s",errorMsg); } else NSLog(@"数据插入成功"); sqlite3_finalize(stmt); [self closeDataBase]; }这里需要注意的是:
sqlite3_bind_text(stmt, <span style="color:#ff0000;"><strong>1</strong></span>, student.name.UTF8String, -1, nil); sqlite3_bind_text(stmt, <span style="color:#ff0000;"><strong>2</strong></span>, student.age.UTF8String, -1, nil); sqlite3_bind_text(stmt, <span style="color:#ff0000;"><strong>3</strong></span>, student.address.UTF8String, -1, nil);这里的1 2 3 的顺序是根据创建表单时name、age和address的顺序来的。
sqlite3_bind_text是数据的类型。
下面是SQLite3里面支持的数据类型:
sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,void(*)(void*));
sqlite3_bind_double(sqlite3_stmt*, int, double);
sqlite3_bind_int(sqlite3_stmt*, int, int);
sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
sqlite3_bind_null(sqlite3_stmt*, int);
sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,void(*)(void*), unsigned char encoding);
sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
sqlite3_prepare_v2(dataBase, insterSQL.UTF8String, -1, &stmt, nil中的5各参数:
第一个参数:dataBase是一个sqlite3类型的数据;
第二个参数:是SQL语句;第三个参数:-1表示传递的C字符串的长度,这样表示函数将使用整个字符串。对于其他情况,需要指定所传递数据的长度。
第四个参数:stmt是一个sqlite3_stmt类型的。
第五个参数:是可选调的函数回调,用于在语句执行后完成内存清理工作。通常这种函数使用malloc()释放以分配的内存。
/** * 更新一个学生的数据 * * @param student 学生数据模型 */ - (void)updateStudent:(Student *)student{ if (![self openDataBase]) { return; } NSString *updateSQL = [NSString stringWithFormat:@"UPDATE %@ SET age = '%@' WHERE name = '%@'",TABLE_NAME,student.age,student.name]; char *errorMsg; if (sqlite3_exec(dataBase, updateSQL.UTF8String, NULL, NULL, &errorMsg) == SQLITE_OK) { NSLog(@"数据更新成功"); [self closeDataBase]; } else{ NSLog(@"数据修改失败:%s",errorMsg); } }
/** * 根据姓名删除学生 * * @param student 学生模型 */ - (void)deleteStudent:(Student *)student{ if (![self openDataBase]) { return; } NSString *deleteSQL = [NSString stringWithFormat:@"DELETE FROM %@ WHERE name = '%@'",TABLE_NAME,student.name]; char *errorMsg; if (sqlite3_exec(dataBase, deleteSQL.UTF8String, NULL, NULL, &errorMsg) == SQLITE_OK) { NSLog(@"数据删除成功"); [self closeDataBase]; } else{ NSLog(@"数据删除失败:%s",errorMsg); } } /** * 删除全部数据 */ - (void)deleteAllStudent{ if (![self openDataBase]) { return; } NSString *deleteSQL = [NSString stringWithFormat:@"DELETE FROM %@ WHERE 1>0",TABLE_NAME]; char *errorMsg; if (sqlite3_exec(dataBase, deleteSQL.UTF8String, NULL, NULL, &errorMsg) == SQLITE_OK) { NSLog(@"数据删除成功"); [self closeDataBase]; } else{ NSLog(@"数据删除失败:%s",errorMsg); } }
/** * 根据学生姓名查找学生 * * @param student 学生数据模型 * * @return 同一个姓名的学生 */ - (NSMutableArray *)selectStudent:(Student *)student{ if (![self openDataBase]) { return nil; } NSMutableArray *dataArray = [[NSMutableArray alloc] init]; NSString *selecteSQL = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE name = '%@'",TABLE_NAME,student.name]; sqlite3_stmt *stmt; if (sqlite3_prepare_v2(dataBase, selecteSQL.UTF8String, -1, &stmt, nil) == SQLITE_OK) { NSLog(@"筛选成功"); while (sqlite3_step(stmt) == SQLITE_ROW) { NSMutableString *name=[NSMutableString stringWithCString:(char*)sqlite3_column_text(stmt, 1) encoding:NSUTF8StringEncoding]; NSMutableString *age=[NSMutableString stringWithCString:(char*)sqlite3_column_text(stmt, 2) encoding:NSUTF8StringEncoding]; NSString *address=[NSString stringWithCString:(char*)sqlite3_column_text(stmt, 3) encoding:NSUTF8StringEncoding]; Student *stu = [Student creatStudent:name age:age address:address]; [dataArray addObject:stu]; } sqlite3_finalize(stmt); [self closeDataBase]; return dataArray; } else{ NSLog(@"筛选失败"); return nil; } } /** * 获取数据库里面的全部数据 * * @return 学生数据的集合 */ - (NSMutableArray *)selectAllStudent{ if (![self openDataBase]) { return nil; } NSMutableArray *dataArray = [[NSMutableArray alloc] init]; NSString *selecteSQL = [NSString stringWithFormat:@"SELECT * FROM %@",TABLE_NAME]; sqlite3_stmt *stmt; if (sqlite3_prepare_v2(dataBase, selecteSQL.UTF8String, -1, &stmt, nil) == SQLITE_OK) { NSLog(@"筛选成功"); while (sqlite3_step(stmt) == SQLITE_ROW) { NSMutableString *name=[NSMutableString stringWithCString:(char*)sqlite3_column_text(stmt, 1) encoding:NSUTF8StringEncoding]; NSMutableString *age=[NSMutableString stringWithCString:(char*)sqlite3_column_text(stmt, 2) encoding:NSUTF8StringEncoding]; NSString *address=[NSString stringWithCString:(char*)sqlite3_column_text(stmt, 3) encoding:NSUTF8StringEncoding]; Student *stu = [Student creatStudent:name age:age address:address]; [dataArray addObject:stu]; } sqlite3_finalize(stmt); [self closeDataBase]; return dataArray; } else{ NSLog(@"筛选失败"); return nil; } }
/** * 随机生成一个学生数据模型 * * @return 学生数据模型 */ - (Student *)getStudent{ Student *student = [Student creatStudent:self.nameArray[arc4random()%6] age:[NSString stringWithFormat:@"%u",arc4random()%100] address:[NSString stringWithFormat:@"%u",arc4random()%1000]]; return student; } /** * 插入数据库按钮按下 * * @param sender sender description */ - (IBAction)insterBtnClick:(UIButton *)sender { [self insterStudent:[self getStudent]]; } /** * 更新数据 * * @param sender sender description */ - (IBAction)modifyBtnClick:(UIButton *)sender { [self updateStudent:[Student creatStudent:@"④" age:@"1" address:@"深圳"]]; } /** * 从数据库删除数据 * * @param sender sender description */ - (IBAction)deleteBtnClick:(UIButton *)sender { [self deleteStudent:[Student creatStudent:@"②" age:nil address:nil]]; } /** * 清空数据库 * * @param sender sender description */ - (IBAction)clearAll:(UIButton *)sender { [self deleteAllStudent]; } /** * 查找同一个姓名的学生 * * @param sender sender description */ - (IBAction)selectBtnClick:(UIButton *)sender { NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:[self selectStudent:[Student creatStudent:@"①" age:nil address:nil]]]; [arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { Student *student = (Student *)obj; NSLog(@"name = %@",student.name); NSLog(@"age = %@",student.age); NSLog(@"address = %@",student.address); }]; } /** * 获取全部数据 * * @param sender sender description */ - (IBAction)selectAllBtnClick:(UIButton *)sender { NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:[self selectAllStudent]]; [arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { Student *student = (Student *)obj; NSLog(@"name = %@",student.name); NSLog(@"age = %@",student.age); NSLog(@"address = %@",student.address); }]; }打开数据库文件就可以看见刚才写入的数据了。