• IOS 数据存储之 SQLite具体解释


      在IOS开发中常常会须要存储数据,对于比較少量的数据能够採取文件的形式存储,比方使用plist文件、归档等,可是对于大量的数据,就须要使用数据库,在IOS开发中数据库存储能够直接通过SQL訪问数据库,也能够通过ORM进行对象关系的映射,当然也能够选择使用第三方框架实现对数据库的操作。在这里。主要来解说一下第一种方式,SQLite。

    SQLite

      数据库有非常多,分为重量级和轻量级两类,移动设备的内存比較小,因此须要选择轻量级的数据库。

    在移动设备上应用程序开发中使用数据库。比較主流的是SQLite。SQLite支持跨平台,尽管是轻量级的数据库。可是它的功能非常强大。其功能不亚于非常多大型的关系数据库。

      SQLite基于C语言开发的轻型数据库,因此须要使用C语言语法进行数据库操作、訪问。不能直接使用OC语言訪问数据库。此外,SQLite中採用的是动态数据类型,即使创建时定义了一种类型,在实际操作时也能够存储其它类型,可是推荐建库时使用合适的类型,特别是应用须要考虑跨平台的情况时。

      SQLite能够直接在代码中使用,可是在开发的过程中。最好安装一个能够直接打开数据库的工具。来验证对数据库的操作是否正确,方便程序调试。大家能够去SQLite官方站点下载Mac OSX系统下的命令行工具。也能够使用类似于SQLiteManager、MesaSQLite等工具。

      数据库的使用,主要包含对数据库的打开关闭、创建表格、对数据库中的数据进行增删改查以及更新等操作。实际上也就是通常所讲的SQL语句,SQLite中的SQL语法并没有太大的区别,因此这里对于SQL语句的内容只是多赘述。大家能够參考其它SQL相关的内容,在这里,我们来具体解说一下在IOS开发中的SQLite的使用。

    SQLite使用步骤:

      1. 在项目中导入libsqlite3.0.dylib框架

      2. 获取数据库的路径。通常是获得获得沙盒中Document目录路径,然后拼接得到数据库路径

      3. 创建或者打开数据库,须要注意的是,在打开的时候须要使用C语言,因此须要先将路径转为C的字符串。然后通过sqlite3_open()打开数据库。假设文件存在则直接打开,否则创建并打开。依据sqlite3_open()返回值来推断是否正确成功打开,假设成功打开。就能够使用得到的sqlite3类型的对象,来对数据库进行其它操作。

      4. 运行写好的SQL语句,对数据库进行操作。运行SQL语句有两种,一种是无返回值语句,比方创建、添加、删除等,一种是有返回值的语句。比方查询。

    (1). 对于无返回值的语句(如添加、删除、改动等)直接通过sqlite3_exec()函数运行。因此能够封装一个方法。用于除查询以外的操作

    (2). 对于有返回值的语句则首先通过sqlite3_prepare_v2()进行sql语句评估(语法检測)。然后通过sqlite3_step()依次取出查询结果的每一行数据,对于每行数据都能够通过相应的sqlite3_column_类型()方法获得相应列的数据。如此重复循环直到遍历完毕。当然,最后须要释放句柄。

      5. SQLite操作是持久连接,在整个操作过程中无需管理数据库连接,假设使用完成。能够选择通过sqlite3_close()手动关闭数据库

    SQLite使用代码

       导入框架。如图所看到的

    //  ViewController.m
    //  JRSQLite查询3
    //
    //  Created by jerehedu on 15/6/16.
    //  Copyright (c) 2015年 jerehedu. All rights reserved.
    //
    
    #import "ViewController.h"
    #import <sqlite3.h>
    
    @interface ViewController ()
    {
        sqlite3 *db;  //声明数据库对象
    }
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 获得数据库路径
        // 获得沙盒中Document目录路径
        NSString *dbPath = [self getUserDocumentPath];
        // 拼接得到数据库路径
        NSString *sqlitePath = [dbPath stringByAppendingPathComponent:@"test.sqlite"];
        
        // 创建或打开数据库
        const char *p = [sqlitePath UTF8String];
        int res = sqlite3_open(p, &db);
        if (res==SQLITE_OK) {
            NSLog(@"db open");
         
            //<一>创建表格
            NSString *sql = @"create table if not exists temps (t_id integer primary key autoincrement,t_name varchar(20) )";
            if ([self execNoQueryWithSQL:sql]) {
                NSLog(@"table temps is created");
            }
            
            //<二>插入数据
            NSString *insert_Sql = @"insert into temps (t_name) values ('pear')";
            if ([self execNoQueryWithSQL:insert_Sql]) {
                NSLog(@"table insert ");
            }
            
            //<三>删除数据
            NSString *delete_sql = @"delete from temps where t_id=2";
            if ([self execNoQueryWithSQL:delete_sql]) {
                NSLog(@"table delete ");
            }
            
            //<四>改动数据
            NSString *update_sql = @"update temps set t_name='ios' where t_id=1";
            if ([self execNoQueryWithSQL:update_sql]) {
                NSLog(@"table update ");
            }
            
            //<五>查询简单的数据1
            NSString *select_sql1 = @"select * from temps where t_id=1";
            sqlite3_stmt *stmt1 = [self execQueryWithSQL:select_sql1];
            while (sqlite3_step(stmt1) == SQLITE_ROW) {
                //依照当前列的类型选数据,列数从0開始
                int t_id = sqlite3_column_int(stmt1, 0);
                const unsigned char *t_name = sqlite3_column_text(stmt1, 1);
                NSString *name = [NSString stringWithUTF8String:(char*)t_name];
                NSLog(@"%i %@",t_id,name);
            }
            //释放stmt statement
            sqlite3_finalize(stmt1);
            
            //<五>查询数据2 參数化的sql语句  查找id>2 而且名字以p开头的
            //用?占位
            int seachId2 = 2;
            NSString *seach_name = @"p%";
            NSString *seach_sql = @"select * from temps where t_id>? and t_name like ?";
            sqlite3_stmt *stmt6 = [self execQueryWithSQL:seach_sql andWithParams:@[[NSNumber numberWithInt:seachId2],seach_name]];
            
            //准备运行(相当于点击run query),运行的时候是一行一行的运行
            while (sqlite3_step(stmt6) == SQLITE_ROW) {
                //依照当前列的类型选数据,列数从0開始
                int t_id = sqlite3_column_int(stmt6, 0);
                const unsigned char *t_name = sqlite3_column_text(stmt6, 1);
                NSString *name = [NSString stringWithUTF8String:(char*)t_name];
                NSLog(@"..>>>>>>...%i %@",t_id,name);
            }
            
            sqlite3_finalize(stmt6);
        }
        
        // 关闭数据库
        sqlite3_close(db);
    }
    
    #pragma mark - 获得沙盒sandbox里面document目录路径
    - (NSString *)getUserDocumentPath
    {
        NSArray *path  = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentPath = [path firstObject];
        return documentPath;
    }
    
    #pragma mark - 运行除查找以外的数据库操作方法
    -(BOOL)execNoQueryWithSQL:(NSString*)sql
    {
        /*
         运行
         參数1:sqlite3 对象
         參数2:c形式的 sql语句
         參数3:回调函数
         參数4:回调函数的參数
         參数5:错误信息(能够char类型指针接受错误信息,用来查错使用)
         */
        if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
            return YES;
        }
        return NO;
    }
    
    #pragma mark 返回查询结果集(简单无參)
    -(sqlite3_stmt *)execQueryWithSQL:(NSString*)sql
    {
        //运行sql语句之后,返回的结果语句
        sqlite3_stmt *stmt;
        /*
         准备运行查询的sql语句 (相当于把查询语句写好)
         參数3:sql语句长度,通经常使用-1表示(系统会自己主动计算)。也能够用strlength函数计算
         參数4:sql_stmt对象 (运行的对象)
         參数5:未运行的sql语句
         */
        int pre_res = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL);
        //假设准备成功
        if (pre_res == SQLITE_OK) {
            return stmt;
        }
        return NULL;
    }
    
    #pragma mark - 返回查询结果集(有參数的)
    -(sqlite3_stmt *)execQueryWithSQL:(NSString *)sql andWithParams:(NSArray *)params
    {
        sqlite3_stmt *stmt;
        int pre_res = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL);
        if (pre_res == SQLITE_OK) {
            //有參数。循环绑定參数
            if (params!=nil) {
                for (int i=0; i<params.count; i++) {
                    
                    id obj = params[i];
                    //绑定的数据类型可能为NSString或者NSNumber,或者数据为空。分别推断
                    if (obj==nil) {
                        //假设数据为nil
                        sqlite3_bind_null(stmt, i+1);
                    }
                    else if ([obj respondsToSelector:@selector(objCType)])
                    {
                        //当前的绑定的数据类型位NSNumber
                        //NSNumber推断包装的是int?longInt?shortInt?float?double?
                        /*
                         strstr(參数1,參数2) (strstr() c中函数搜索一个字符串在还有一个字符串中的第一次出现,则该函数返回第一次匹配的字符串的地址,找不到返回NULL)
                         推断參数1中的字符在參数2的字符串char*中出现的索引
                         [obj objCType] 假设obj是int返回字符串i
                         */
                        if (strstr("ilsILS", [obj objCType])) {
                            /*
                             绑定參数 假设有where
                             參数1:sqlite_stmt对象 (statement结果集)
                             參数2:占位符索引 从1開始
                             參数3:替代占位符的真实參数
                             */
                            sqlite3_bind_int(stmt, i+1, [obj intValue]);
                        }
                        else if (strstr("fdFD", [obj objCType]))
                        {
                            sqlite3_bind_double(stmt, i+1, [obj doubleValue]);
                        }
                        else
                        {
                            stmt = nil;
                        }
                    }
                    else if ([obj respondsToSelector:@selector(UTF8String)])
                    {
                        //当前的绑定的数据类型位NSString 推断是否有UTF8String方法
                        //用bind替换占位符 索引从1開始
                        sqlite3_bind_text(stmt, i+1, [obj UTF8String], -1, NULL);
                    }
                    else
                    {
                        stmt = nil;
                    }
                }
                
                return stmt;
            }
        }
        
        return NULL;
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
    }
    
    @end

     

      疑问咨询或技术交流,请增加官方QQ群:JRedu技术交流 (452379712)

    作者:杰瑞教育
    出处:http://blog.csdn.net/jerehedu/ 
    本文版权归烟台杰瑞教育科技有限公司和CSDN共同拥有。欢迎转载。但未经作者允许必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
  • 相关阅读:
    CDQ分治·学习笔记
    高斯消元板子
    [HEOI2012]朋友圈
    [CTSC2008]祭祀
    Medium | LeetCode 140. 单词拆分 II | 回溯(递归)
    Hard | LeetCode 212. 单词搜索 II | 回溯 + 前缀树
    Medium | LeetCode 131. 分割回文串 | 回溯 + 动态规划预处理
    Hard | LeetCode 329. 矩阵中的最长递增路径 | 矩阵+DFS
    Hard | LeetCode 76. 最小覆盖子串 | 滑动窗口
    Medium | LeetCode 130. 被围绕的区域 | 矩阵 + DFS
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7025819.html
Copyright © 2020-2023  润新知