<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [深入淺出iOS庫]之數據庫 sqlite

      [深入淺出iOS庫]之數據庫 sqlite

      羅朝輝 (http://www.rzrgm.cn/kesalin/)

      本文遵循“署名-非商業用途-保持一致”創作公用協議

      一,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, 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, address, age from customer";
          sqlite3_stmt * statement;
          int state = sqlite3_prepare_v2(database, sqlCmd, -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, address, 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];

       

      posted @ 2013-03-28 23:45  飄飄白云  閱讀(4203)  評論(1)    收藏  舉報
      本博客遵循 Creative Commons License “署名-非商業用途-保持一致”創作共用協議。 與我聯系
      主站蜘蛛池模板: 亚洲日本中文字幕天天更新| 亚洲国产精品日韩在线| 人妻中文字幕精品系列| 国产成人午夜福利院| 熟女精品色一区二区三区| 久久精品不卡一区二区| 国产午夜精品久久精品电影| 中文字幕av中文字无码亚| 国产成人精品一区二区三区| 欧美激情综合色综合啪啪五月| 成人无码潮喷在线观看| 伊人久久大香线蕉综合观| 视频一区视频二区制服丝袜 | 草草浮力影院| 美腿丝袜亚洲综合第一页| 久久综合伊人77777| 国产精品激情| 亚洲av伦理一区二区| 国产福利姬喷水福利在线观看| 欧美性受xxxx黑人猛交| 亚洲跨种族黑人xxxxx| 在线观看精品日本一区二| 日韩一区二区三区日韩精品| 999国产精品999久久久久久| 日韩亚av无码一区二区三区| 二区中文字幕在线观看| 丰满熟女人妻一区二区三| 一级做a爰片在线播放| 中文字幕在线无码一区二区三区| 午夜精品视频在线看| 99国产欧美另类久久久精品| 亚洲中文字幕精品一区二区三区 | 色伦专区97中文字幕| 日韩深夜福利视频在线观看| 国产精品99一区二区三区| 青青草一区在线观看视频| 久久久久香蕉国产线看观看伊| 国产午夜福利视频在线| 久久中文字幕一区二区| 郯城县| 一区二区三区av天堂|