SQLite3sql
SQLite3簡介數據庫
SQLite3是一款開源的嵌入式關係型數據庫,可移植性好、易使用、內存開銷小。框架
SQLite3是無類型的,意味着你能夠保存任何類型的數據到任意表的任意字段中。好比下列的創表語句是合法的:函數
1
|
create table t_person(name, age);
|
爲了保證可讀性,建議仍是把字段類型加上:url
1
|
create table t_person(name text, age integer);
|
SQLite3經常使用的5種數據類型:text、integer、float、boolean、blobspa
在iOS中使用SQLite3,首先要添加庫文件libsqlite3.dylib和導入主頭文件3d
導入庫日誌
建立或打開數據庫code
1
2
3
|
// path爲:~/Documents/person.db
sqlite3 *db;
int result = sqlite3_open([path UTF8String], &db);
|
代碼解析:orm
sqlite3_open()將根據文件路徑打開數據庫,若是不存在,則會建立一個新的數據庫。若是result等於常量SQLITE_OK,則表示成功打開數據庫
sqlite3 *db:一個打開的數據庫實例
數據庫文件的路徑必須以C字符串(而非NSString)傳入
關閉數據庫:sqlite3_close(db);
執行創表語句
1
2
3
|
char *errorMsg;
// 用來存儲錯誤信息
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;
帶佔位符插入數據
1
2
3
4
5
6
7
8
9
10
|
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 *對象
查詢數據
1
2
3
4
5
6
7
8
9
10
11
12
|
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開始
Core Data
Core Data簡單介紹
Core Data框架提供了對象-關係映射(ORM)的功能,即可以將OC對象轉化成數據,保存在SQLite3數據庫文件中,也可以將保存在數據庫中的數據還原成OC對象。在此數據操做期間,不須要編寫任何SQL語句。使用此功能,要添加CoreData.framework和導入主頭文件CoreData/CoreData.h。
對象-關係映射
在Core Data,須要進行映射的對象稱爲實體(entity),並且須要使用Core Data的模型文件來描述應用的全部實體和實體屬性
這裏以Person和Card(身份證)2個實體爲例子,先看看實體屬性和之間的關聯關係
實體屬性和之間的關聯關係
Person中有個Card屬性,Card中有個Person屬性。
屬於一對一雙向關聯。
模型文件
建立文件
添加實體
添加Person實體的基本屬性
添加Card實體的基本屬性
在Person中添加card屬性
在Card中添加person屬性
NSManagedObject
經過Core Data從數據庫取出的對象,默認狀況下都是NSManagedObject對象
NSManagedObject的工做模式有點相似於NSDictionary對象,經過鍵-值對來存取全部的實體屬性
setValue:forKey: 存儲屬性值(屬性名爲key)
valueForKey: 獲取屬性值(屬性名爲key)
Core Data主要對象
搭建Core Data上下文環境
從應用程序包中加載模型文件
1
|
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
|
傳入模型,初始化NSPersistentStoreCoordinator
1
|
NSPersistentStoreCoordinator *psc = [[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model] autorelease];
|
構建SQLite文件路徑
1
2
|
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@
"person.data"
]];
|
添加持久化存儲庫,這裏使用SQLite做爲存儲庫
1
2
3
4
5
|
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
if
(store == nil) {
// 直接拋異常
[NSException raise:@
"添加數據庫錯誤"
format:@
"%@"
, [error localizedDescription]];
}
|
初始化上下文,設置persistentStoreCoordinator屬性
1
2
3
|
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = psc;
// 用完以後,仍是要[context release];
|
添加數據
傳入上下文,建立一個Person實體對象
1
|
NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:@
"Person"
inManagedObjectContext:context];
|
設置簡單屬性
1
2
|
[person setValue:@
"hosea"
forKey:@
"name"
];
[person setValue:[NSNumber numberWithInt:22] forKey:@
"age"
];
|
傳入上下文,建立一個Card實體對象
1
2
|
NSManagedObject *card = [NSEntityDescription insertNewObjectForEntityForName:@
"Card"
inManagedObjectContext:context];
[card setValue:@
"4414241933432"
forKey:@
"no"
];
|
設置Person和Card之間的關聯關係
1
|
[person setValue:card forKey:@
"card"
];
|
利用上下文對象,將數據同步到持久化存儲庫
1
2
3
4
5
6
|
NSError *error = nil;
BOOL success = [context save:&error];
if
(!success) {
[NSException raise:@
"訪問數據庫錯誤"
format:@
"%@"
, [error localizedDescription]];
}
//若是是想作更新操做:只要在更改了實體對象的屬性後調用[context save:&error],就能將更改的數據同步到數據庫
|
查詢數據
初始化一個查詢請求
1
|
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
|
設置要查詢的實體
1
|
NSEntityDescription *desc = [NSEntityDescription entityForName:@
"Person"
inManagedObjectContext:context];
|
設置排序(按照age降序)
1
2
|
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@
"age"
ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];
|
設置條件過濾(name like '%hosea-1%')
1
2
|
NSPredicate *predicate = [NSPredicate predicateWithFormat:@
"name like %@"
, @
"*hosea-1*"
];
request.predicate = predicate;
|
執行請求
1
2
3
4
5
|
NSError *error = nil;
NSArray *objs = [context executeFetchRequest:request error:&error];
if
(error) {
[NSException raise:@
"查詢錯誤"
format:@
"%@"
, [error localizedDescription]];
}
|
遍歷數據
1
2
3
|
for
(NSManagedObject *obj
in
objs) {
NSLog(@
"name=%@"
, [obj valueForKey:@
"name"
]);
}
|
刪除數據
傳入須要刪除的實體對象
1
|
[context deleteObject:managedObject];
|
將結果同步到數據庫
1
2
3
4
5
|
NSError *error = nil;
[context save:&error];
if
(error) {
[NSException raise:@
"刪除錯誤"
format:@
"%@"
, [error localizedDescription]];
}
|
打開Core Data的SQL日誌輸出開關
Core Data的延遲加載
Core Data不會根據實體中的關聯關係當即獲取相應的關聯對象
好比經過Core Data取出Person實體時,並不會當即查詢相關聯的Card實體;當應用真的須要使用Card時,纔會查詢數據庫,加載Card實體的信息
建立NSManagedObject的子類
默認狀況下,利用Core Data取出的實體都是NSManagedObject類型的,可以利用鍵-值對來存取數據
可是通常狀況下,實體在存取數據的基礎上,有時還須要添加一些業務方法來完成一些其餘任務,那麼就必須建立NSManagedObject的子類
選擇模型文件
選擇須要建立子類的實體
那麼生成一個Person實體對象就應該這樣寫
1
2
3
4
5
6
|
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@
"Person"
inManagedObjectContext:context];
person.name = @
"hosea"
;
person.age = [NSNumber numberWithInt:22];
Card *card = [NSEntityDescription insertNewObjectForEntityForName:@」Card" inManagedObjectContext:context];
card.no = @」4414245465656";
person.card = card;
|