標籤:
SQLite
主流嵌入式關聯式資料庫:輕量級,跨平台 基於C語言,在ios中需要用C語言進行資料庫操作採用動態資料類型,即使建立時定義了一種類型,在實際操作時也可以儲存其他類型,推薦建庫時使用合適的類型(跨平台)建立串連後通常不需要關閉串連(可以手動關閉) 使用SQLite步驟,先在項目中匯入libsqlite3架構
1.開啟庫:sqlite3_open(),指定一個資料庫檔案儲存路徑,如果檔案存在就直接開啟,否則就建立然後開啟,得到一個sqlite3類型的對象
2.執行sql語句3.如果沒有傳回值(增刪改),sqlite3_exec()執行4.如果有傳回值(查),sqlite3_perpare_v2()文法檢測,sqlite3_step()依次取出查詢結果的每一行資料,sqlite3_column_類型()方法獲得對應列迴圈便利類似於遊標-------------------------------------------------------------------------------------------------------------------------------------------基本寫法
//// DbManager.h// DataAccess//// Created by Kenshin Cui on 14-3-29.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import <Foundation/Foundation.h>#import <sqlite3.h>#import "KCSingleton.h"@interface KCDbManager : NSObjectsingleton_interface(KCDbManager);#pragma mark - 屬性#pragma mark 資料庫引用,使用它進行資料庫操作@property (nonatomic) sqlite3 *database;#pragma mark - 共有方法/** * 開啟資料庫 * * @param dbname 資料庫名稱 */-(void)openDb:(NSString *)dbname;/** * 執行無傳回值的sql * * @param sql sql語句 */-(void)executeNonQuery:(NSString *)sql;/** * 執行有傳回值的sql * * @param sql sql語句 * * @return 查詢結果 */-(NSArray *)executeQuery:(NSString *)sql;@end
主要定義了一個sqlite3 的資料庫物件,一個開啟資料庫openDb方法一個執行無傳回值的方法executeNonQuery方法一個執行有傳回值的方法executeQuery方法sqlite不支援預存程序
//// DbManager.m// DataAccess//// Created by Kenshin Cui on 14-3-29.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import "KCDbManager.h"#import <sqlite3.h>#import "KCSingleton.h"#import "KCAppConfig.h"#ifndef kDatabaseName#define kDatabaseName @"myDatabase.db"#endif@interface KCDbManager()@end@implementation KCDbManagersingleton_implementation(KCDbManager)#pragma mark 重寫初始化方法-(instancetype)init{ KCDbManager *manager; if((manager=[super init])) { [manager openDb:kDatabaseName]; } return manager;}-(void)openDb:(NSString *)dbname{ //取得資料庫儲存路徑,通常儲存沙箱Documents目錄 NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSLog(@"%@",directory); NSString *filePath=[directory stringByAppendingPathComponent:dbname]; //如果有資料庫則直接開啟,否則建立並開啟(注意filePath是ObjC中的字串,需要轉化為C語言字串類型) if (SQLITE_OK ==sqlite3_open(filePath.UTF8String, &_database)) { NSLog(@"資料庫開啟成功!"); }else{ NSLog(@"資料庫開啟失敗!"); }}-(void)executeNonQuery:(NSString *)sql{ char *error; //逐步執行sql語句,用於插入、修改、刪除 if (SQLITE_OK!=sqlite3_exec(_database, sql.UTF8String, NULL, NULL,&error)) { NSLog(@"執行SQL語句過程中發生錯誤!錯誤資訊:%s",error); }}-(NSArray *)executeQuery:(NSString *)sql{ NSMutableArray *rows=[NSMutableArray array];//資料行 //評估文法正確性 sqlite3_stmt *stmt; //檢查文法正確性 if (SQLITE_OK==sqlite3_prepare_v2(_database, sql.UTF8String, -1, &stmt, NULL)) { //逐步執行sql語句int columnCount= sqlite3_column_count(stmt);
while (SQLITE_ROW==sqlite3_step(stmt)) { NSMutableDictionary *dic=[NSMutableDictionary dictionary]; for (int i=0; i<columnCount; i++) { const char *name= sqlite3_column_name(stmt, i);//取得列名 const unsigned char *value= sqlite3_column_text(stmt, i);//取得某列的值 dic[[NSString stringWithUTF8String:name]]=[NSString stringWithUTF8String:(const char *)value]; } [rows addObject:dic]; } } //釋放控制代碼 sqlite3_finalize(stmt); return rows;}
-------------------------------------------------------------------------------------------------------------------------------------------
分析 重寫初始化方法init,在初始化的時候執行opendb,開啟資料庫(名字字串通過#define 來定義)opendb方法中先取得資料庫的儲存地址,然後開啟
//取得資料庫儲存路徑,通常儲存沙箱Documents目錄(這一步是取沙箱目錄) NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; //傳入資料庫名字字串得到資料庫地址 NSString *filePath=[directory stringByAppendingPathComponent:dbname];//如果有資料庫則直接開啟,否則建立並開啟(注意filePath是ObjC中的字串,需要轉化為C語言字串類型) sqlite3_open(filePath.UTF8String, &_database)
executeNonQuery直接執行sql語句,無傳回值(其實是有傳回值的SQLite_OK表示語句是否執行成功)
sqlite3_exec(_database, sql.UTF8String, NULL, NULL,&error)
executeQuery先檢查sql語句的文法,有傳回值,一條一條的讀資料首先需要一個整體的存放資料的數組(相當於C#的DataTable.Rows集合)
NSMutableArray *rows=[NSMutableArray array];//資料行
然後需要一個sqlite3_stmt對象檢查文法
//評估文法正確性 sqlite3_stmt *stmt;
然後檢查文法
//檢查文法正確性 if (SQLITE_OK==sqlite3_prepare_v2(_database, sql.UTF8String, -1, &stmt, NULL))
然後迴圈執行(類似於遊標,一行一行的讀,每行都要檢查文法)
while (SQLITE_ROW==sqlite3_step(stmt))
然後定義一個NSmutableDicrtionary,用於接受每一行的資料,這一行的每一列的列名就是dic的鍵名,dic的值就是這一列這行對應的值,然後將這個dic添加到存放資料的數組
while (SQLITE_ROW==sqlite3_step(stmt)) { NSMutableDictionary *dic=[NSMutableDictionary dictionary]; for (int i=0; i<columnCount; i++) { const char *name= sqlite3_column_name(stmt, i);//取得列名 const unsigned char *value= sqlite3_column_text(stmt, i);//取得某列的值 dic[[NSString stringWithUTF8String:name]]=[NSString stringWithUTF8String:(const char *)value]; } [rows addObject:dic];
最後釋放檢查文法的控制代碼(不知道是什麼意思) 在實際使用的時候,Controller不直接和db進行互動,而是通過一個Service層間接完成資料的傳遞,Service層封裝了針對Model層的業務方法,Controller針對Service中對Model方法的調用實際上就是對db的操作。完成瞭解耦 -------------------------------------------------------------------------------------------------------------------------------------------
實際應用 待續.....
2015.9.29-資料存取(SQLite)