iOS开发中数据库的使用笔记
iOS中的数据存储方式
Plist:(NSArray\NSDictionary),只能存储数组,字典,但是数组和字典里面不能有自定义对象
Preference:(偏好设置\NSUserDefaults)
NSCoding(NSKeyedArchiver\NSkeyedUnarchiver)
SQLite3: Navicat数据库管理软件,支持大部分主流数据库(包括SQLite)Ps:用Navicat建表时建议以t_开头,实际上SQLite是无类型的
Core Data
SQL(structured query language):结构化查询语言
SQL语句的种类:
DDL:Data Definition Language 数据定义语句
常用操作:create,drop
- 创建表格:create table if not exists t_class (id integer primary KEY autoincrement ,name text)
- 删除表格:drop table if exists t_class
DML:Data Manipulation Language 数据操作语句
常用操作:insert,update,delete
- 插入:insert into t_class (name,age) values(‘taofei’,18);
insert into t_class (name) values(‘taofei0610’);
- 更新:update t_class set name=’taofei’;//values(taofei0610);
update t_class set name=’taofei0610’ where name=’taofei’
- 删除:delete from t_class name
- NSString *qpl=[NSString stringWithFormat:@”“];
DQL:Data Query Language 数据查询语句
常用操作:select,where,order by,group by,having
- not null,unique,default,desc ,asc
- select name from student where age>10 and gender=’man’ order dy id desc
- select * from t_student order by age desc ;; //降序
- select * from t_student order by age asc ; // 升序(默认)
- select * from t_student order by age asc, height desc ;
- select * from t_student limit 4, 8 ;//可以理解为:跳过最前面4条语句,然后取8条记录,limit常用来做分页查询
- 相当于select * from t_student limit 0, 7 ;//select * from t_student limit 7 ;
- 外键:name fk_status_user fields user_id referenced table t_user id
- create table if not exists t_student (id integer primary key autoincrement,name text,age integer,class_id integer,constraint fk_student_class foreign key(class_id) referenced class)
- 表连接查询(多表查询):select s.name sName,c.name cName from t_student s , t_class c where s.class_id=c.id;
create table t_student (id integer, name text not null unique, age integer not null default 1) ;
create table t_student (id integer primary key, name text, age integer) ;
create table t_student (id integer primary key autoincrement, name text, age integer) ;
create table t_student (id integer primary key autoincrement, name text, age integer, class_id integer, constraint fk_t_student_class_id_t_class_id foreign key (class_id) references t_class (id);//约束与外键的使用
select s.name,s.age from t_student s, t_class c where s.class_id = c.id and c.name = ‘0512iOS’;
内连接:inner join 或者 join (显示的是左右表都有完整字段值的记录)
左外连接:left outer join (保证左表数据的完整性)
SQLite实现本地缓存:增删改查;
- 1.打开数据库,就会创建数据库文件:#import
#
创建或打开数据库
// path是数据库文件的存放路径
sqlite3 *db = NULL;
int result = sqlite3_open([path UTF8String], &db);
代码解析:
sqlite3_open()将根据文件路径打开数据库,如果不存在,则会创建一个新的数据库。如果result等于常量SQLITE_OK,则表示成功打开数据库
sqlite3 *db:一个打开的数据库实例
数据库文件的路径必须以C字符串(而非NSString)传入
关闭数据库:sqlite3_close(db);
执行创表语句
char *errorMsg = NULL; // 用来存储错误信息
char *sql = “create table if not exists t_person(id integer primary key autoincrement, name text, age integer);”;
int result = sqlite3_exec(db, sql, NULL, NULL, &errorMsg);
代码解析:
sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。但是一般不用它执行查询语句,因为它不会返回查询到的数据
sqlite3_exec()还可以执行的语句:
开启事务:begin transaction;
回滚事务:rollback;
提交事务:commit;
char *sql = "insert into t_person(name, age) values(?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, "母鸡", -1, NULL);
sqlite3_bind_int(stmt, 2, 27);
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
NSLog(@"插入数据错误");
}
sqlite3_finalize(stmt);
代码解析:
sqlite3_prepare_v2()返回值等于SQLITE_OK,说明SQL语句已经准备成功,没有语法问题
sqlite3_bind_text():大部分绑定函数都只有3个参数
第1个参数是sqlite3_stmt *类型
第2个参数指占位符的位置,第一个占位符的位置是1,不是0
第3个参数指占位符要绑定的值
第4个参数指在第3个参数中所传递数据的长度,对于C字符串,可以传递-1代替字符串的长度
第5个参数是一个可选的函数回调,一般用于在语句执行后完成内存清理工作
sqlite_step():执行SQL语句,返回SQLITE_DONE代表成功执行完毕
sqlite_finalize():销毁sqlite3_stmt *对象
char *sql = "select id,name,age from t_person;";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
int _id = sqlite3_column_int(stmt, 0);
char *_name = (char *)sqlite3_column_text(stmt, 1);
NSString *name = [NSString stringWithUTF8String:_name];
int _age = sqlite3_column_int(stmt, 2);
NSLog(@"id=%i, name=%@, age=%i", _id, name, _age);
}
}
sqlite3_finalize(stmt);
代码解析
sqlite3_step()返回SQLITE_ROW代表遍历到一条新记录
sqlite3_column_*()用于获取每个字段对应的值,第2个参数是字段的索引,从0开始
FMDB
什么是FMDB
FMDB是iOS平台的SQLite数据库框架
FMDB以OC的方式封装了SQLite的C语言API
FMDB的优点
使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
对比苹果自带的Core Data框架,更加轻量级和灵活
提供了多线程安全的数据库操作方法,有效地防止数据混乱
FMDB的github地址
基本使用:核心类
- FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
- FMResultSet:使用FMDatabase执行查询后的结果集
- FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的
打开数据库
通过指定SQLite数据库文件路径来创建FMDatabase对象
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@”数据库打开失败!”);
}文件路径有三种情况
具体文件路径
如果不存在会自动创建空字符串@””
会在临时目录创建一个空的数据库
当FMDatabase连接关闭时,数据库文件也被删除nil
会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁
执行更新
- 在FMDB中,除查询以外的所有操作,都称为“更新”;create、drop、insert、update、delete等
- 使用executeUpdate:方法执行更新
- (BOOL)executeUpdate:(NSString*)sql, …
- (BOOL)executeUpdateWithFormat:(NSString*)format, …
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
[db executeUpdate:@”UPDATE t_student SET age = ? WHERE name = ?;”, @20, @”Jack”]
执行查询
查询方法
-(FMResultSet )executeQuery:(NSString)sql, …
- -(FMResultSet )executeQueryWithFormat:(NSString)format, …
- -(FMResultSet )executeQuery:(NSString )sql withArgumentsInArray:(NSArray *)arguments
示例
// 查询数据
FMResultSet rs = [db executeQuery:@”SELECT FROM t_student”];
// 遍历结果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@”name”];
int age = [rs intForColumn:@”age”];
double score = [rs doubleForColumn:@”score”];
}
FMDatabaseQueue
- FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题
- 为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类
- FMDatabaseQueue的创建
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
简单使用
[queue inDatabase:^(FMDatabase *db) {
[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]) {
// …
}
}];