在iPhone的開發過程中常常會用到數據庫,而SQLite3是iPhone中支持的數據庫。下面簡單介紹一下iPhone中SQLite3數據庫的用法:
SQLite3簡介
SQLite3是一個輕量級的數據庫,完全使用C語言編寫,使用簡單方便。它是一個嵌入到程序進程的數據庫,和其他一些數據庫(MySQL,MS SQL)不同,它沒有獨立的進程。
1、打開數據庫
首先聲明一個數據庫變量
sqlite3 *db = NULL;
每一個SQLite3都是一個文件,打開一個數據庫只需要調用一次sqlite3_open函數:
SQLITE_API int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
filename是數據庫的路徑,ppDb是指向返回的sqlite3數據庫,返回SQLITE3_OK則表示正常。比如我們打開Document目錄下的“Test.db”數據庫:
int result = sqlite3_open([dbPath UTF8String], &db);
NSAssert(result==SQLITE_OK, @”Can’t open database %@”, dbPath);
注意:如果dbPath路徑下的數據庫不存在,那么打開這個數據庫將會創建一個空的數據庫。
2、執行SQL語句
SQLite3有3種執行SQL語句的方法:
- 通過sqlite3_exec()函數,適用於執行(非查詢)語句:如CREATE TABLE、INSERT,REPLACE,DELETE等。
SQLITE_API int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
比如我們要創建一個表示個人(person)的表,就可以使用sqlite3_exec()函數。person表中包括名字(name)、性別(gender)、年齡(age)和生日(birthday)這幾個字段。代碼如下:
char *errmsg = NULL;
result = sqlite3_exec(db, “CREATE TABLE person (”
“name TEXT,”
“gender INTEGER,”
“age INTEGER,”
“birthday DATE)”, NULL, NULL, &errmsg);
NSAssert(result==SQLITE_OK, @”Can’t CREATE TABLE: %s”, errmsg);
- 通過sqlite3_get_table()函數,適用於查詢語句SELECT。由於此函數返回一個字符串數組,因此對於要求結果為二進制數據(如圖像數據)的不能用此函數返回。
SQLITE_API int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
例如我們要查詢person中的所有數據:
char **table = NULL;
int row,col;
result = sqlite3_get_table(db, “SELECT name,age,birthday from person”, &table, &row, &col, &errmsg);
NSAssert(result==SQLITE_OK, @”SQL ERROR: %s”, errmsg);
那么字符串數組table中就包含所有的表信息,本例中每行3個元素(name、age和birthday),table第一行元素是字段名字,如table[0]是”name”,table[1]是”age”,table[2]是”birthday”。table的第二行才是實際的數據,如table[3]是”張三”,table[4]是”24″,table[5]是”1981-10-21 12:00:01″。
- 通過sqlite3_prepare()、sqlite3_step()、sqlite3_bind_xxx()以及sqlite3_finalize()等一系列函數,可以逐行獲取數據,並可以獲取二進制數據。
sqlite3_prepare()用於編譯一個SQL語句,返回一個sqlite3_stmt結構指針。sqlite3_stmt結構指針用於sqlite3_step()、sqlite3_bind_xxx()以及sqlite3_finalize()等函數中。sqlite3_step()用於將當前記錄指向下一個。sqlite3_bind_xxx()等一系列函數會獲取當前記錄中各個字段對應的值。最后調用一下sqlite3_finalize()用於釋放一些資源。
下面是高級的應用
H文件
#import <Foundation/Foundation.h>
#import "sqlite3.h"
@interface DatabaseOperation : NSObject {
sqlite3 *m_sql;
NSString *m_dbName;
}
@property(nonatomic)sqlite3* m_sql;
@property(nonatomic,retain)NSString* m_dbName;
-(id)initWithDbName:(NSString*)dbname;
-(BOOL)openOrCreateDatabase:(NSString*)DbName;
-(BOOL)createTable:(NSString*)sqlCreateTable;
-(void)closeDatabase;
-(BOOL)InsertTable:(NSString*)sqlInsert;
-(BOOL)UpdataTable:(NSString*)sqlUpdata;
-(NSArray*)querryTable:(NSString*)sqlQuerry;
-(NSArray*)querryTableByCallBack:(NSString*)sqlQuerry;
@end
M文件
#import "DatabaseOperation.h"
@implementation DatabaseOperation
@synthesize m_sql;
@synthesize m_dbName;
- (id) initWithDbName:(NSString*)dbname
{
self = [super init];
if (self != nil) {
if ([self openOrCreateDatabase:dbname]) {
[self closeDatabase];
}
}
return self;
}
- (id) init
{
NSAssert(0,@"Never Use this.Please Call Use initWithDbName:(NSString*)");
return nil;
}
- (void) dealloc
{
self.m_sql = nil;
self.m_dbName =nil;
[super dealloc];
}
//-------------------創建數據庫-------------------------
-(BOOL)openOrCreateDatabase:(NSString*)dbName
{
self.m_dbName = dbName;
NSArray *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [path objectAtIndex:0];
if(sqlite3_open([[documentsDirectorystringByAppendingPathComponent:dbName]UTF8String],&m_sql) !=SQLITE_OK)
{
NSLog(@"創建數據庫失敗");
return NO;
}
return YES;
}
//------------------創建表----------------------
-(BOOL)createTable:(NSString*)sqlCreateTable
{
if (![selfopenOrCreateDatabase:self.m_dbName]) {
return NO;
}
char *errorMsg;
if (sqlite3_exec (self.m_sql, [sqlCreateTable UTF8String],NULL,NULL, &errorMsg) != SQLITE_OK)
{
NSLog(@"創建數據表失敗:%s",errorMsg);
return NO;
}
[selfcloseDatabase];
return YES;
}
//----------------------關閉數據庫-----------------
-(void)closeDatabase
{
sqlite3_close(self.m_sql);
}
//------------------insert-------------------
-(BOOL)InsertTable:(NSString*)sqlInsert
{
if (![selfopenOrCreateDatabase:self.m_dbName]) {
return NO;
}
char* errorMsg = NULL;
if(sqlite3_exec(self.m_sql, [sqlInsertUTF8String],0,NULL, &errorMsg) ==SQLITE_OK)
{ [selfcloseDatabase];
returnYES;}
else {
printf("更新表失敗:%s",errorMsg);
[selfcloseDatabase];
return NO;
}
return YES;
}
//--------------updata-------------
-(BOOL)UpdataTable:(NSString*)sqlUpdata{
if (![selfopenOrCreateDatabase:self.m_dbName]) {
return NO;
}
char *errorMsg;
if (sqlite3_exec (self.m_sql, [sqlUpdata UTF8String],0,NULL, &errorMsg) !=SQLITE_OK)
{
[selfcloseDatabase];
returnYES;
}else {
returnNO;
}
return YES;
}
//--------------select---------------------
-(NSArray*)querryTable:(NSString*)sqlQuerry
{
if (![selfopenOrCreateDatabase:self.m_dbName]) {
return nil;
}
int row = 0;
int column = 0;
char* errorMsg = NULL;
char** dbResult = NULL;
NSMutableArray* array = [[NSMutableArrayalloc]init];
if(sqlite3_get_table(m_sql, [sqlQuerryUTF8String], &dbResult, &row,&column,&errorMsg ) ==SQLITE_OK)
{
if (0 == row) {
[self closeDatabase];
return nil;
}
int index = column;
for(int i =0; i < row ; i++ ) {
NSMutableDictionary* dic = [[NSMutableDictionaryalloc]init];
for(int j =0 ; j < column; j++ ) {
if (dbResult[index]) {
NSString* value = [[NSStringalloc]initWithUTF8String:dbResult[index]];
NSString* key = [[NSStringalloc]initWithUTF8String:dbResult[j]];
[dic setObject:value forKey:key];
[value release];
[key release];
}
index ++;
}
[array addObject:dic];
[dic release];
}
}else {
printf("%s",errorMsg);
[selfcloseDatabase];
return nil;
}
[selfcloseDatabase];
return [array autorelease];
}
//----------------------select--------------------
int processData(void* arrayResult,int columnCount,char** columnValue,char** columnName)
{
int i;
NSMutableDictionary* dic = [[NSMutableDictionaryalloc]init];
for( i = 0 ; i < columnCount; i ++ )
{
if (columnValue[i]) {
NSString* key = [[NSStringalloc]initWithUTF8String:columnName[i]];
NSString* value = [[NSStringalloc]initWithUTF8String:columnValue[i]];
[dic setObject:value forKey:key];
}
}
[(NSMutableArray*)arrayResult addObject:dic];
[dic release];
return 0;
}
//---------------------select-----------------------
-(NSArray*)querryTableByCallBack:(NSString*)sqlQuerry
{
if (![selfopenOrCreateDatabase:self.m_dbName]) {
return nil;
}
char* errorMsg = NULL;
NSMutableArray* arrayResult = [[NSMutableArrayalloc]init];
if (sqlite3_exec(self.m_sql,[sqlQuerryUTF8String],processData,(void*)arrayResult,&errorMsg) !=SQLITE_OK) {
printf("查詢出錯:%s",errorMsg);
}
[selfcloseDatabase];
return [arrayResult autorelease];
}
@end