• IOS-SQLite数据库使用详解


    使用SQLite数据库

    创建数据库

    创建数据库过程需要3个步骤:

    1、使用sqlite3_open函数打开数据库;

    2、使用sqlite3_exec函数执行Create Table语句,创建数据库表;

    3、使用sqlite3_close函数释放资源。

    这个过程中使用了3个SQLite3函数,它们都是纯C语言函数,通过Objective-C去调用C函数当然不是什么问题,但是也要注意Objective-C数据类型与C数据类型兼容性问题。

    下 面我们使用SQLite技术实现备忘录案例,与属性列表文件实现一样,我们只需要修改持久层工程(PersistenceLayer)中NoteDAO类 就可以了。首先我们需要添加SQLite3库到工程环境中,有3个工程需要添加到哪个呢?应该添加到可以运行的工程即表示层工程 PresentationLayer。选择工程PresentationLayer中 TARGETS→PresentationLayer→Link Binary With Libraries,点击左下角的“+”,弹出对话框选择 libsqlite3.dylib或libsqlite3.0.dylib,在弹出的对话框中点击Add添加。

    NoteDAO.h文件的修改:

    Cpp代码  收藏代码
    1. #import ”Note.h”  
    2.   
    3. #import ”sqlite3.h”  
    4.   
    5.    
    6.   
    7. #define DBFILE_NAME @”NotesList.sqlite3″  
    8.   
    9.    
    10.   
    11. @interface NoteDAO : NSObject  
    12.   
    13. {  
    14.   
    15. sqlite3 *db;  
    16.   
    17. }  
    18.   
    19.    
    20.   
    21. + (NoteDAO*)sharedManager;  
    22.   
    23.    
    24.   
    25. - (NSString *)applicationDocumentsDirectoryFile;  
    26.   
    27. - (void)createEditableCopyOfDatabaseIfNeeded;  
    28.   
    29.    
    30.   
    31. //插入Note方法  
    32.   
    33. -(int) create:(Note*)model;  
    34.   
    35.    
    36.   
    37. //删除Note方法  
    38.   
    39. -(int) remove:(Note*)model;  
    40.   
    41.    
    42.   
    43. //修改Note方法  
    44.   
    45. -(int) modify:(Note*)model;  
    46.   
    47.    
    48.   
    49. //查询所有数据方法  
    50.   
    51. -(NSMutableArray*) findAll;  
    52.   
    53.    
    54.   
    55. //按照主键查询数据方法  
    56.   
    57. -(Note*) findById:(Note*)model;  
    58.   
    59.    
    60.   
    61. @end  



    我们需要使用语句#import ”sqlite3.h”引入sqlite3头文件,而且需要定义sqlite3*成员变量db。NoteDAO.m中的createEditableCopyOfDatabaseIfNeeded方法:

    Cpp代码  收藏代码
    1. - (void)createEditableCopyOfDatabaseIfNeeded {  
    2.   
    3.    
    4.   
    5. NSString *writableDBPath = [self applicationDocumentsDirectoryFile];  
    6.   
    7. if (sqlite3_open([writableDBPath UTF8String], &db) != SQLITE_OK) { ①  
    8.   
    9. sqlite3_close(db);  ②  
    10.   
    11. NSAssert(NO,@”数据库打开失败。”);  
    12.   
    13. else {  
    14.   
    15. char *err;  
    16.   
    17. NSString *createSQL = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS Note  
    18.   
    19. (cdate TEXT PRIMARY KEY, content TEXT);"]; ③  
    20.   
    21. if (sqlite3_exec(db,[createSQL UTF8String],NULL,NULL,&err) != SQLITE_OK) { ④  
    22.   
    23. sqlite3_close(db); ⑤  
    24.   
    25. NSAssert1(NO, @”建表失败, %s”, err);  ⑥  
    26.   
    27. }  
    28.   
    29. sqlite3_close(db);  ⑦  
    30.   
    31. }  
    32.   
    33. }  



    createEditableCopyOfDatabaseIfNeeded方法用于创建数据库,第1步打开数据 库,代码①行,语句是 sqlite3_open([writableDBPath UTF8String], &db),sqlite3_open函数的第1个参数是 数据库文件完整的路径,但是需要注意的是在SQLite3函数中接受的是char*的UTF-8类型数据,需要将NSString*转换为UTF-8,使 用NSString*的UTF8String方法可以转换,sqlite3_open函数第2个参数sqlite3指针变量db的地址。该函数的返回值是 int类型,在SQLite3中定义了很多常量,返回值等于常量SQLITE_OK则说明操作成功。

    第2步执行建表语句,代码第④行,语句 sqlite3_exec(db,[createSQL UTF8String],NULL,NULL,&err)执行建表的SQL。第1个参数 是sqlite3指针变量db的地址,第2个参数是要执行的sql语句,第3个参数是要回调函数,第4个参数是要回调函数的参数,第5个参数是执行出错的 字符串。建表SQL语句是,如果表Note存在这不用创建。

    CREATE TABLE IF NOT EXISTS Note (cdate TEXT PRIMARY KEY, content TEXT)

    第3步使用sqlite3_close函数释放资源,代码②、⑤、⑦行所示,在数据库打开失败、Create Table执行失败和成功执行完成时候调用。原则上无论正常结束还是异常结束必须使用sqlite3_close函数释放资源。

    查询数据

    数据查询一般会带有查询条件,这个使用SQL语句where子句很容易实现,但是在程序中需要动态绑定参数给where子句。执行查询数据步骤如下:

    1、使用sqlite3_open函数打开数据库;

    2、使用sqlite3_prepare_v2函数预处理SQL语句;

    3、使用sqlite3_bind_text函数绑定参数;

    4、使用sqlite3_step函数执行SQL语句,遍历结果集;

    5、使用sqlite3_column_text等函数提取字段数据;

    6、使用sqlite3_finalize和sqlite3_close函数释放资源。

    NoteDAO.m中的按照主键查询数据方法:

    Cpp代码  收藏代码
    1. -(Note*) findById:(Note*)model  
    2.   
    3. {  
    4.   
    5. NSString *path = [self applicationDocumentsDirectoryFile];  
    6.   
    7. if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { ①  
    8.   
    9. sqlite3_close(db);  ②  
    10.   
    11. NSAssert(NO,@”数据库打开失败。”);  
    12.   
    13. else {  
    14.   
    15.    
    16.   
    17. NSString *qsql = @”SELECT cdate,content FROM Note where cdate =?”;  
    18.   
    19.    
    20.   
    21. sqlite3_stmt *statement;  
    22.   
    23. //预处理过程  
    24.   
    25. if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) { ③  
    26.   
    27. //准备参数  
    28.   
    29. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; ④  
    30.   
    31. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];  
    32.   
    33. NSString *nsdate = [dateFormatter stringFromDate:model.date];  
    34.   
    35. //绑定参数开始  
    36.   
    37. sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL); ⑤  
    38.   
    39. //执行  
    40.   
    41. if (sqlite3_step(statement) == SQLITE_ROW) { ⑥  
    42.   
    43. char *cdate = (char *) sqlite3_column_text(statement, 0); ⑦  
    44.   
    45. NSString *nscdate = [[NSString alloc] initWithUTF8String: cdate];  
    46.   
    47.    
    48.   
    49. char *content = (char *) sqlite3_column_text(statement, 1);  
    50.   
    51. NSString * nscontent = [[NSString alloc] initWithUTF8String: content];  
    52.   
    53. Note* note = [[Note alloc] init];  
    54.   
    55. note.date = [dateFormatter dateFromString:nscdate];  
    56.   
    57. note.content = nscontent;  
    58.   
    59.    
    60.   
    61. sqlite3_finalize(statement);  
    62.   
    63. sqlite3_close(db);  
    64.   
    65. return note;  
    66.   
    67. }  
    68.   
    69. }  
    70.   
    71.    
    72.   
    73. sqlite3_finalize(statement); ⑧  
    74.   
    75. sqlite3_close(db);  ⑨  
    76.   
    77.    
    78.   
    79. }  
    80.   
    81. return nil;  
    82.   
    83. }  



    该方法执行了6个步骤,其中第1个步骤,代码第①行所示,它与创建数库的第1个步骤是一样的,不用再介绍了。

    第 2个步骤,代码第③行所示,语句 sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL)是预处理 SQL语句,预处理目的是将SQL编译成二进制代码,提高SQL语句执行的速度。sqlite3_prepare_v2函数的第3个参数-1代表全部 sql字符串长度,第4个参数&statement是sqlite3_stmt指针的地址,它是语句对象,通过语句对象可以执行SQL语句,第5 个参数是sql语句没有被执行的部分语句。

    第3个步骤,代码第⑤行所示,语句sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL)是绑定SQL语句参数。在SQL语句中带有问号,这个问号就是要绑定的参数,问号是占位符。

    NSString *qsql = @”SELECT cdate,content FROM Note where cdate =?”;

    sqlite3_bind_text函数是绑定参数,第1个参数是statement指针,第2个参数为序号(从1开始),第3个参数为字符串值,第4个参数为字符串长度,第5个参数为一个函数指针。

    第4个步骤sqlite3_step(statement)执行SQL语句,代码第⑥行所示,sqlite3_step返回int类型,等于SQLITE_ROW说明还要其它的行没有遍历。

    第 5个步骤提取字段数据,代码第⑦行所示,使用sqlite3_column_text(statement, 0)函数可以读取字符串类型字段,第2参数 是指定select字段的索引(从0开始)。同样char*转换成为NSString*类型,需要initWithUTF8String:构造方法。读取 字段函数采用与字段类型有关系,SQLite3的类似的常用函数还有:

    sqlite3_column_blob()

    sqlite3_column_double()

    sqlite3_column_int()

    sqlite3_column_int64()

    sqlite3_column_text()

    sqlite3_column_text16()

    关于其它的API可以参考http://www.sqlite.org/cintro.html。

    第6个步骤是释放资源,创建数据库过程不同,除了使用sqlite3_close函数关闭数据库,代码第⑧行所示,还要使用sqlite3_finalize函数释放语句对象statement代码第⑨行所示。

    NoteDAO.m中的查询所有数据方法:

    Cpp代码  收藏代码
    1. -(NSMutableArray*) findAll  
    2.   
    3. {  
    4.   
    5. NSString *path = [self applicationDocumentsDirectoryFile];  
    6.   
    7. NSMutableArray *listData = [[NSMutableArray alloc] init];  
    8.   
    9. if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {  
    10.   
    11. sqlite3_close(db);  
    12.   
    13. NSAssert(NO,@”数据库打开失败。”);  
    14.   
    15. else {  
    16.   
    17.    
    18.   
    19. NSString *qsql = @”SELECT cdate,content FROM Note”;  
    20.   
    21.    
    22.   
    23. sqlite3_stmt *statement;  
    24.   
    25. //预处理过程  
    26.   
    27. if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) {  
    28.   
    29. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];  
    30.   
    31. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];  
    32.   
    33. //执行  
    34.   
    35. while (sqlite3_step(statement) == SQLITE_ROW) {  
    36.   
    37. char *cdate = (char *) sqlite3_column_text(statement, 0);  
    38.   
    39. NSString *nscdate = [[NSString alloc] initWithUTF8String: cdate];  
    40.   
    41.    
    42.   
    43. char *content = (char *) sqlite3_column_text(statement, 1);  
    44.   
    45. NSString * nscontent = [[NSString alloc] initWithUTF8String: content];  
    46.   
    47. Note* note = [[Note alloc] init];  
    48.   
    49. note.date = [dateFormatter dateFromString:nscdate];  
    50.   
    51. note.content = nscontent;  
    52.   
    53. [listData addObject:note];  
    54.   
    55. }  
    56.   
    57. }  
    58.   
    59.    
    60.   
    61. sqlite3_finalize(statement);  
    62.   
    63. sqlite3_close(db);  
    64.   
    65.    
    66.   
    67. }  
    68.   
    69. return listData;  
    70.   
    71. }  



    查询所有数据方法与按照主键查询数据方法类似,区别在于本方法没有查询条件不需要绑定参数。遍历的时候使用while循环语句,不是if语句。

    while (sqlite3_step(statement) == SQLITE_ROW) {

    … …

    }

    修改数据 

    修改数据包括:insert、update和delete语句。这3个SQL语句都可以带有参数,关于参数的绑定与查询where子句绑定的方式是一样的。执行修改数据步骤如下:

    1、使用sqlite3_open函数打开数据库;

    2、使用sqlite3_prepare_v2函数预处理SQL语句;

    3、使用sqlite3_bind_text函数绑定参数;

    4、使用sqlite3_step函数执行SQL语句;

    5、使用sqlite3_finalize和sqlite3_close函数释放资源。

    修改数据的步骤与查询数据的步骤相比少了一个提取字段数据步骤。下面我们看看代码部分。其它的步骤是一样的。

    NoteDAO.m中的插入Note方法:

    Cpp代码  收藏代码
    1. -(int) create:(Note*)model  
    2.   
    3. {  
    4.   
    5. NSString *path = [self applicationDocumentsDirectoryFile];  
    6.   
    7. if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { ①  
    8.   
    9. sqlite3_close(db);  ②  
    10.   
    11. NSAssert(NO,@”数据库打开失败。”);  
    12.   
    13. else {  
    14.   
    15.    
    16.   
    17. NSString *sqlStr = @”INSERT OR REPLACE INTO note (cdate, content) VALUES (?,?)”;  
    18.   
    19.    
    20.   
    21. sqlite3_stmt *statement;  
    22.   
    23. //预处理过程  
    24.   
    25. if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) { ③  
    26.   
    27. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];  
    28.   
    29. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];  
    30.   
    31. NSString *nsdate = [dateFormatter stringFromDate:model.date];  
    32.   
    33. //绑定参数开始  
    34.   
    35. sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);  ④  
    36.   
    37. sqlite3_bind_text(statement, 2, [model.content UTF8String], -1, NULL);  
    38.   
    39.    
    40.   
    41. //执行插入  
    42.   
    43. if (sqlite3_step(statement) != SQLITE_DONE) { ⑤  
    44.   
    45. NSAssert(NO, @”插入数据失败。”);  
    46.   
    47. }  
    48.   
    49. }  
    50.   
    51.    
    52.   
    53. sqlite3_finalize(statement);  ⑥  
    54.   
    55. sqlite3_close(db);  ⑦  
    56.   
    57. }  
    58.   
    59. return 0;  
    60.   
    61. }  



    第⑤行代码sqlite3_step(statement)语句执行插入语句,常量SQLITE_DONE执行完成。

    NoteDAO.m中的删除Note方法:

    Cpp代码  收藏代码
      1. -(int) remove:(Note*)model  
      2.   
      3. {  
      4.   
      5. NSString *path = [self applicationDocumentsDirectoryFile];  
      6.   
      7. if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {  
      8.   
      9. sqlite3_close(db);  
      10.   
      11. NSAssert(NO,@”数据库打开失败。”);  
      12.   
      13. else {  
      14.   
      15.    
      16.   
      17. NSString *sqlStr = @”DELETE  from note where cdate =?”;  
      18.   
      19.    
      20.   
      21. sqlite3_stmt *statement;  
      22.   
      23. //预处理过程  
      24.   
      25. if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {  
      26.   
      27. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];  
      28.   
      29. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];  
      30.   
      31. NSString *nsdate = [dateFormatter stringFromDate:model.date];  
      32.   
      33. //绑定参数开始  
      34.   
      35. sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);  
      36.   
      37. //执行插入  
      38.   
      39. if (sqlite3_step(statement) != SQLITE_DONE) {  
      40.   
      41. NSAssert(NO, @”删除数据失败。”);  
      42.   
      43. }  
      44.   
      45. }  
      46.   
      47.    
      48.   
      49. sqlite3_finalize(statement);  
      50.   
      51. sqlite3_close(db);  
      52.   
      53. }  
      54.   
      55. return 0;  
      56.   
      57. }  
      58.   
      59. NoteDAO.m中的修改Note方法:  
      60.   
      61. -(int) modify:(Note*)model  
      62.   
      63. {  
      64.   
      65. NSString *path = [self applicationDocumentsDirectoryFile];  
      66.   
      67. if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {  
      68.   
      69. sqlite3_close(db);  
      70.   
      71. NSAssert(NO,@”数据库打开失败。”);  
      72.   
      73. else {  
      74.   
      75.    
      76.   
      77. NSString *sqlStr = @”UPDATE note set content=? where cdate =?”;  
      78.   
      79.    
      80.   
      81. sqlite3_stmt *statement;  
      82.   
      83. //预处理过程  
      84.   
      85. if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {  
      86.   
      87. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];  
      88.   
      89. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];  
      90.   
      91. NSString *nsdate = [dateFormatter stringFromDate:model.date];  
      92.   
      93. //绑定参数开始  
      94.   
      95. sqlite3_bind_text(statement, 1, [model.content UTF8String], -1, NULL);  
      96.   
      97. sqlite3_bind_text(statement, 2, [nsdate UTF8String], -1, NULL);  
      98.   
      99. //执行插入  
      100.   
      101. if (sqlite3_step(statement) != SQLITE_DONE) {  
      102.   
      103. NSAssert(NO, @”修改数据失败。”);  
      104.   
      105. }  
      106.   
      107. }  
      108.   
      109.    
      110.   
      111. sqlite3_finalize(statement);  
      112.   
      113. sqlite3_close(db);  
      114.   
      115. }  
      116.   
      117. return 0;  
      118.   
      119. }  
  • 相关阅读:
    mysql replication常见错误整理
    enq: TX
    LOGMNR分析redo log和archive log教程
    使用create datafile... as ...迁移数据文件到裸设备
    mysql无法启动,报错 Can't start server: can't create PID file: No space left on device
    MYSQL 权限设置查询
    ORA-02437 违反主键
    oracle sequence的用法
    sequence有关问题
    关于Relay Log无法自动删除的问题
  • 原文地址:https://www.cnblogs.com/oc-bowen/p/5345972.html
Copyright © 2020-2023  润新知