
創(chuàng)建、打開、關(guān)閉數(shù)據(jù)庫
- 創(chuàng)建或打開數(shù)據(jù)庫
// path為:~/Documents/person.db
sqlite3 *db;
int result = sqlite3_open([path UTF8String], &db);
?代碼解析:
?sqlite3_open()將根據(jù)文件路徑打開數(shù)據(jù)庫,如果不存在,則會創(chuàng)建一個新的數(shù)據(jù)庫。如果result等于常量SQLITE_OK,則表示成功打開數(shù)據(jù)庫
sqlite3 *db:一個打開的數(shù)據(jù)庫實例
數(shù)據(jù)庫文件的路徑必須以C字符串(而非NSString)傳入
#執(zhí)行不返回數(shù)據(jù)的SQL語句
- 執(zhí)行創(chuàng)表語句
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()可以執(zhí)行任何SQL語句,比如創(chuàng)表、更新、插入和刪除操作。但是一般不用它執(zhí)行查詢語句,因為它不會返回查詢到的數(shù)據(jù)
sqlite3_exec()還可以執(zhí)行的語句:
開啟事務(wù):begin transaction;
回滾事務(wù):rollback;
提交事務(wù):commit;
帶占位符插入數(shù)據(jù)
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(@"插入數(shù)據(jù)錯誤");
}
sqlite3_finalize(stmt);
代碼解析:
- sqlite3_prepare_v2()返回值等于SQLITE_OK,說明SQL語句已經(jīng)準(zhǔn)備成功,沒有語法問題
- sqlite3_bind_text():大部分綁定函數(shù)都只有3個參數(shù)
- 第1個參數(shù)是sqlite3_stmt *類型
- 第2個參數(shù)指占位符的位置,第一個占位符的位置是1,不是0
-? 第3個參數(shù)指占位符要綁定的值
- 第4個參數(shù)指在第3個參數(shù)中所傳遞數(shù)據(jù)的長度,對于C字符串,可以傳遞-1代替字符串的長度
- 第5個參數(shù)是一個可選的函數(shù)回調(diào),一般用于在語句執(zhí)行后完成內(nèi)存清理工作
- sqlite_step():執(zhí)行SQL語句,返回SQLITE_DONE代表成功執(zhí)行完畢
- sqlite_finalize():銷毀sqlite3_stmt *對象
查詢數(shù)據(jù)
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_*()用于獲取每個字段對應(yīng)的值,
Core Data

模型文件




NSManagedObject

Core Data主要對象

搭建Core Data上下文環(huán)境
// 從應(yīng)用程序包中加載模型文件
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
// 傳入模型,初始化NSPersistentStoreCoordinator
NSPersistentStoreCoordinator *psc = [[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model] autorelease];
// 構(gòu)建SQLite文件路徑
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"person.data"]];
// 添加持久化存儲庫,這里使用SQLite作為存儲庫
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
if (store == nil) { // 直接拋異常
[NSException raise:@"添加數(shù)據(jù)庫錯誤" format:@"%@", [error localizedDescription]];
}
// 初始化上下文,設(shè)置persistentStoreCoordinator屬性
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = psc;
// 用完之后,還是要[context release];
添加數(shù)據(jù)
// 傳入上下文,創(chuàng)建一個Person實體對象
NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
// 設(shè)置簡單屬性
[person setValue:@"MJ" forKey:@"name"];
[person setValue:[NSNumber numberWithInt:27] forKey:@"age"];
// 傳入上下文,創(chuàng)建一個Card實體對象
NSManagedObject *card = [NSEntityDescription insertNewObjectForEntityForName:@"Card" inManagedObjectContext:context];
[card setValue:@"4414241933432" forKey:@"no"];
// 設(shè)置Person和Card之間的關(guān)聯(lián)關(guān)系
[person setValue:card forKey:@"card"];
// 利用上下文對象,將數(shù)據(jù)同步到持久化存儲庫
NSError *error = nil;
BOOL success = [context save:&error];
if (!success) {
[NSException raise:@"訪問數(shù)據(jù)庫錯誤" format:@"%@", [error localizedDescription]];
}
// 如果是想做更新操作:只要在更改了實體對象的屬性后調(diào)用[context save:&error],就能將更改的數(shù)據(jù)同步到數(shù)據(jù)庫
查詢數(shù)據(jù)
// 初始化一個查詢請求
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
// 設(shè)置要查詢的實體
NSEntityDescription *desc = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
// 設(shè)置排序(按照age降序)
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];
// 設(shè)置條件過濾(name like '%Itcast-1%')
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*Itcast-1*"];
request.predicate = predicate;
// 執(zhí)行請求
NSError *error = nil;
NSArray *objs = [context executeFetchRequest:request error:&error];
if (error) {
[NSException raise:@"查詢錯誤" format:@"%@", [error localizedDescription]];
}
// 遍歷數(shù)據(jù)
for (NSManagedObject *obj in objs) {
NSLog(@"name=%@", [obj valueForKey:@"name"]
}
刪除數(shù)據(jù)
// 傳入需要刪除的實體對象
[context deleteObject:managedObject];
//將結(jié)果同步到數(shù)據(jù)庫
NSError *error = nil;
[context save:&error];
if (error) {
[NSException raise:@"刪除錯誤" format:@"%@", [error localizedDescription]];
}
打開Core Data的SQL日志輸出開關(guān)

Core Data的延遲加載
- Core Data不會根據(jù)實體中的關(guān)聯(lián)關(guān)系立即獲取相應(yīng)的關(guān)聯(lián)對象
- 比如通過Core Data取出Person實體時,并不會立即查詢相關(guān)聯(lián)的Card實體;當(dāng)應(yīng)用真的需要使用Card時,才會查詢數(shù)據(jù)庫,加載Card實體的信息
創(chuàng)建NSManagedObject的子類



// 那么生成一個Person實體對象就應(yīng)該這樣寫
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
person.name = @"MJ";
person.age = [NSNumber numberWithInt:27];
Card *card = [NSEntityDescription insertNewObjectForEntityForName:@”Card" inManagedObjectContext:context];
card.no = @”4414245465656";
person.card = card;