加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

i os sqlite

发布时间:2020-12-12 19:54:01 所属栏目:百科 来源:网络整理
导读:一,sqlite 简介 前面写了一篇博文讲如何在 C# 中使用 ADO 访问各种数据库,在移动开发和嵌入式领域也有一个轻量级的开源关系型数据库-sqlite。它的特点是零配置(无需服务器),单磁盘文件存储数据(就像fopen一样),平台无关性,使用起来简单又高效。这些

一,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. %@" 
  
 
  • 关闭数据库
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,0)">errorMsg);
    if (state == SQLITE_OK) {
        DLOG(@" >> Succeed to %@" {
        DLOG(@" >> Failed to %@. Error: %@" 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)" 
 
  • 查询操作
  • 查询操作稍微负责一点,需要创建查询描述(sqlite3_stmt),然后调用如下接口编译成字节程序:

    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*,0)"> iCol);
    SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*,0)"> iCol);
    SQLITE_API double sqlite3_column_double(sqlite3_stmt*,0)"> iCol);
    SQLITE_API int sqlite3_column_int(sqlite3_stmt*,0)"> iCol);
    SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*,0)"> iCol);
    SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*,0)"> iCol);
    SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*,0)"> iCol);
    SQLITE_API int sqlite3_column_type(sqlite3_stmt*,0)"> 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,0)">statement,nil);
        if (state == SQLITE_OK) {
            DLOG(@" >> Succeed to prepare statement. %@";
        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++ 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 %@"
        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 (?,?,?)"retValue)
            DLog(@" >> Error: Database failed to insert image %@" ([rs next])
        {
             ....
        }
    
        // query count
        //
        NSInteger count = 0;
        FMResultSet *rs = [db executeQuery:@"SELECT COUNT(*) FROM Image WHERE seriesUid = ?" ([rs next]) {
            count = [rs intForColumnIndex:0];
        }
    
        // delete
        //
        retValue = [db executeUpdate:@"DELETE FROM Image WHERE seriesUid = ?"retValue)
            DLog(@" >> Error: Database failed to delete image by seriesUid %@"(编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读