IOS 深入浅出Cocoa之 sqlite 数据库

IOS 深入浅出Cocoa之 sqlite 数据库,第1张

概述一,sqlite 简介 前面写了一篇博文讲如何在 C# 中使用 ADO 访问各种数据库,在移动开发和嵌入式领域也有一个轻量级的开源关系型数据库-sqlite。它的特点是零配置(无需服务器),单磁盘文件存储数据(就像fopen一样),平台无关性,使用起来简单又高效。这些特点让其非常适合移动开发和嵌入式领域。当然,sqlite 也因其力求简单高效,也就限制了它对并发,海量数据的处理。下面,我就再接再厉 一,sqlite 简介

前面写了一篇博文讲如何在 C# 中使用 ADO 访问各种数据库,在移动开发和嵌入式领域也有一个轻量级的开源关系型数据库-sqlite。它的特点是零配置(无需服务器),单磁盘文件存储数据(就像fopen一样),平台无关性,使用起来简单又高效。这些特点让其非常适合移动开发和嵌入式领域。当然,sqlite 也因其力求简单高效,也就限制了它对并发,海量数据的处理。下面,我就再接再厉,来讲讲如何在 iOS 中使用 sqlite 库和第三方封装库 FMDB,以及介绍一个 MAC 下开源的可视化 sqlite 浏览器。

本文源码:https://github.com/kesalin/iOSSnippet/tree/master/SQLiteDemo

二,在 iOS 中的使用

在 iOS 中 sqlite3 库是一套纯 C 的接口,因此很方便地就可以在 obj-c 源码中无痕使用它,而且其使用方式与用 ADO 方式 *** 作数据库大同小异-少了创建数据库链接一环而已(因为 sqlite 没有服务器的概念也就无需链接了)。

首先,需要引入 libsqlite3.0.dylib:

然后包含头文件:

#import "/usr/include/sqlite3.h"

打开或创建数据库
sqlITE_API int sqlite3_open(  const char *filename,/* Database filename (UTF-8) */  sqlite3 **ppDb          /* OUT: sqlite db handle */);

使用示例:(dbPath 为 Nsstring *)

    // open database    //    int state = sqlite3_open([dbPath UTF8String],&database);    if (state == sqlITE_OK) {        DLOG(@" >> Succeed to open database. %@",dbPath);    }    else {        DLOG(@" >> Failed to open database. %@",dbPath);    }

关闭数据库
sqlITE_API int sqlite3_close(sqlite3 *);

上面这个接口将关闭数据库,如果当前还有事务没有提交,会先执行 rollback *** 作,然后再关闭数据库。

执行 sql 语句

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 */);

这个接口是最常用到的,几乎除了查询之外的 sql 命令都可以用它来 *** 作,比如创建表,插入/更新/删除记录,创建/提交/回滚事务等。注意:如果 errmsg 不为 null,那么当错误发生时, sqlite 就会为错误消息分配内存,返回给调用者,调用者有责任调用 sqlite3_free 来释放这部分内存。为了方便使用,我封装了一个简单的 obj-c 方法:

- (BOol)excutesqlWithCString:(const char *)sqlCmd{    char * errorMsg;    int state = sqlite3_exec(database,sqlCmd,NulL,&errorMsg);    if (state == sqlITE_OK) {        DLOG(@" >> Succeed to %@",[Nsstring stringWithCString:sqlCmd enCoding:NSUTF8StringEnCoding]);    }    else {        DLOG(@" >> Failed to %@. Error: %@",[Nsstring stringWithCString:sqlCmd enCoding:NSUTF8StringEnCoding],[Nsstring stringWithCString:errorMsg enCoding:NSUTF8StringEnCoding]);                sqlite3_free(errorMsg);    }        return (state == sqlITE_OK);}

下面是创建表以及事务 *** 作的使用示例:

- (voID)createtable{    if (database == NulL) {        DLOG(@" >> Database does not open yet.");        return;    }        const char * sqlCmd = "create table if not exists customer (ID integer primary key autoincrement,name text not null,address text,age integer)";        [self excutesqlWithCString:sqlCmd];}- (BOol)beginTransaction{    return [self excutesqlWithCString:"BEGIN EXCLUSIVE TRANSACTION;"];}- (BOol)commit{    return [self excutesqlWithCString:"COMMIT TRANSACTION;"];    }- (BOol)rollback{    return [self excutesqlWithCString:"RolLBACK TRANSACTION;"];}

很简单,不是么?至于插入,更新,删除示例,请参考如下 sqlCmd:

// insert    Nsstring * sqlCmd = [Nsstring stringWithFormat:@"insert into customer (name,address,age) values ('%@','%@',%d)",customer.name,customer.address,customer.age];// update    Nsstring * sqlCmd = [Nsstring stringWithFormat:@"update customer set address='%@',age=%d where name='%@'",newValue.address,newValue.age,oldValue.name];// delete    Nsstring * sqlCmd = [Nsstring stringWithFormat:@"delete from customer where name='%@'",customer.name];

查询 *** 作

查询 *** 作稍微负责一点,需要创建查询描述(sqlite3_stmt),然后调用如下接口编译成字节程序:

sqlITE_API int sqlite3_prepare_v2(  sqlite3 *db,/* Database handle */  const char *zsql,/* sql statement,UTF-8 encoded */  int nByte,/* Maximum length of zsql in bytes. */  sqlite3_stmt **ppStmt,/* OUT: Statement handle */  const char **pzTail     /* OUT: Pointer to unused portion of zsql */);

注意:这里使用的是 v2 - version 2,这是 sqlite 推荐使用的版本,version 1 仅仅是为了向后兼容而保留着。

然后使用如下接口来评估的查询结果:

sqlITE_API int sqlite3_step(sqlite3_stmt*);

如果该接口返回 sqlITE_ROW,表面查询到了一行记录,我们就可以以下接口从查询描述中获取我们想要的值:

sqlITE_API const voID *sqlite3_column_blob(sqlite3_stmt*,int iCol);sqlITE_API int sqlite3_column_bytes(sqlite3_stmt*,int iCol);sqlITE_API int sqlite3_column_bytes16(sqlite3_stmt*,int iCol);sqlITE_API double sqlite3_column_double(sqlite3_stmt*,int iCol);sqlITE_API int sqlite3_column_int(sqlite3_stmt*,int iCol);sqlITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*,int iCol);sqlITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*,int iCol);sqlITE_API const voID *sqlite3_column_text16(sqlite3_stmt*,int iCol);sqlITE_API int sqlite3_column_type(sqlite3_stmt*,int iCol);sqlITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*,int iCol);

最后,需要通过如下接口释放先前创建的查询描述。通常,为了提高查询效率,可以把常用的查询描述缓存起来。

sqlITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);

下面就来看一个具体的使用示例:

- (NSArray *)queryAllCustomers{    NSMutableArray * array = [[NSMutableArray alloc] init];        const char * sqlCmd = "select name,age from customer";    sqlite3_stmt * statement;    int state = sqlite3_prepare_v2(database,-1,&statement,nil);    if (state == sqlITE_OK) {        DLOG(@" >> Succeed to prepare statement. %@",[Nsstring stringWithCString:sqlCmd enCoding:NSUTF8StringEnCoding]);    }        NSInteger index = 0;    while (sqlite3_step(statement) == sqlITE_ROW) {        // get raw data from statement        //        char * cstrname = (char *)sqlite3_column_text(statement,0);        char * csTraddress = (char *)sqlite3_column_text(statement,1);        int age = sqlite3_column_int(statement,2);                Nsstring * name = [Nsstring stringWithCString:cstrname enCoding:NSUTF8StringEnCoding];        Nsstring * address = [Nsstring stringWithCString:csTraddress enCoding:NSUTF8StringEnCoding];        KSCustomer * customer = [[KSCustomer alloc]                                 initWith:name                                 address:address                                 age:age];        [array addobject:customer];                DLOG(@"   >> Record %d : %@ %@ %d",index++,name,age);    }        sqlite3_finalize(statement);        DLOG(@" >> query %d records.",[array count]);    return array;}

三,MAC 下查看 sqlite db 文件的工具

MAC 下有一款不错的开源可视化 sqlite db 浏览器:sqlite Database browser,你可以从以下链接获取:

http://sourceforge.net/projects/sqlitebrowser/

该软件运行界面如下:

四,封装 sqlite 的第三方库 FMDB

在 iOS 中直接使用 sqlite 原生 C 接口还是不那么方便,因此催生了第三方的 iOS 版封装库,其中使用比较广泛又轻量级的就是 FMDB(https://github.com/ccgus/fmdb),目前该库只有六个文件,不超过2000行代码。

使用也是非常简单,在工程中包含这六个文件:

然后包含头文件:

#import "FMDatabase.h"#import "FMResultSet.h"#import "FMDatabaseAdditions.h"

就可以使用该库了:

    // Create database    //    Nsstring * path  = [UIHUtilitIEs configPathFor:kDatabasefile];    FMDatabase db  = [[FMDatabase databaseWithPath:path] retain];        if (![db open])    {          DLog(@" >> Error: Failed to open database at %@",path);    }    #if DEBUG    db.traceExecution = TRUE;#endif        // Create tables    //    [db executeUpdate:@"CREATE table Image (studyUID text,patIEntID text,serIEsUID text,SOPUID text,contentDate text,modality text,patIEntposition text,filepath text,thumbnailPath text)"];    // insert    //    BOol retValue = [db executeUpdate:@"INSERT INTO Image (studyUID,patIEntID,serIEsUID,SOPUID,contentDate,patIEntposition,modality,filepath,thumbnailPath) VALUES (?,?,?)",image.studyUID,image.patIEntID,image.serIEsUID,image.soPUID,image.contentDate,image.patIEntposition,image.modality,image.filepath,image.thumbnailPath];        if (!retValue)        DLog(@" >> Error: Database Failed to insert image %@",image);    // query    //    FMResultSet *rs = [db executequery:@"SELECT * FROM Image WHERE SOPUID = ?",SOPUID];    if ([rs next])    {         ....    }    // query count    //    NSInteger count = 0;    FMResultSet *rs = [db executequery:@"SELECT COUNT(*) FROM Image WHERE serIEsUID = ?",serIEsUID];    if ([rs next]) {        count = [rs intForColumnIndex:0];    }    // delete    //    retValue = [db executeUpdate:@"DELETE FROM Image WHERE serIEsUID = ?",serIEsUID];    if (!retValue)        DLog(@" >> Error: Database Failed to delete image by serIEsUID %@",serIEsUID);    // release database    //    [db release];
总结

以上是内存溢出为你收集整理的IOS 深入浅出Cocoa之 sqlite 数据库全部内容,希望文章能够帮你解决IOS 深入浅出Cocoa之 sqlite 数据库所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1053712.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存