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]) {
// …
}
}];