zoukankan      html  css  js  c++  java
  • iOS进阶第二节 数据读写之SQL数据库

     

    一、数据库管理系统

      1>. SQL语言概述

      SQL是Structured Query Language(结构化查询语句)的缩写,SQL是专门为数据库而扩建的操作命令集,是一种功能齐全的数据库语言。

      2>. 常见的数据库

    • MySQL:MySQL是一个精巧的SQL数据库管理系统,而且是开源的数据管理系统。MySQL主要目标是快速、健全和易用。由于它的强大功能、灵活性、丰富的应用编程接口(API)以及精巧的系统结构,受到了广大自由软件爱好者甚至商业软件用户的青睐。
    • Oracle:Oracle Database,又名Oracle RDNMS,或简称Oracle。是甲骨文公司的一款关系型数据库管理系统。系统可移植性好、使用方便、功能强。

      3>. 数据库定义、分类、特征

    • 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库
    • 数据库可分为关系型数据库(主流)、对象型数据库、层次式数据库。
    • 常见的关系型数据库有:Oracle、MySQL、SQL Server、Access、DB2、Sybase(前六种是PC端)、SQLite(嵌入式移动客服端)
    • 特征①. 以一定方式存储在一起

          ②. 能为多个用户共享

          ③. 具有尽可能少的冗余代码

          ④. 是与程序彼此独立的数据集合

      4>. SQLite数据库

      SQLite是一个轻量级的关系数据库。SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的内存就够了,目前应用于Android、iOS、Windows Phone等智能手机。iOS使用SQLite时,只需要加入libsqlite3.0.tbd依赖以及引入sqlite3.h头文件即可。

      5>. 表、字段、记录(SQL详细学习可到 http://www.w3school.com.cn/sql/index.asp)

    • 表:保存一类数据(例如学生表),是数据库中一个非常重要的对象,是其他对象的基础。根据信息的分类情况,一个数据库中可能包含若干个数据表。
    • 字段:标识本列数据类型,表的"列"称为"字段",每个字段包含某一个专题的信息。
    • 记录:表中一行的信息,是指对应于数据表中一行信息的一组完整的相关信息。

     

    二、SQL语句

      1>.SQLite数据库数据类型

    • SQLite是无类型扥数据库,可以保存任何类型的数据(C语言),对于SQLite来说对字段不指定类型是完全有效的。(注:良好的编程习惯要为字段标注类型)
    • 为了使SQLite和其他数据库之间的兼容性最大化,SQLite支持"类型近似"的观点,列的类型近似指的是存储在列上数据的推荐类型。

      2>. SQLite字段的约束条件

     

      3>. SQL数据库操作语句(不区分大小写)

      ①. 建表命令(Create table)

        create table if not exists 表名 (字段1 约束1 约束2 ..., 字段2 约束1 约束2 ..., ...... );

      ②. 添加表中数据命令(Insert)

        insert into 表名 (字段1, 字段2, ...... ) valuse (字段1值, 字段2值, ...... );

      ③. 更新表中数据命令(Update)

        update 表名 set 字段名1 = 修改值1, 字段名2 = 修改值2, ...... where 条件;

      ④. 删除表中数据命令(Delete)

        delete from 表名 where 条件;

      ⑤. 数据库检索命令(Select)

        select 要查询字段 from 表名 where 条件;

      注1:具体用法可上 w3school 学习(http://www.sqlite.org/docs.html)

       注2:创建和编辑SQLite 数据库需要用到相关插件或者应用,一般的有火狐浏览器的SQLite Manager 插件Navicat Premium 应用

      注3:数据定义语句(DDL:Data Definition Language):包括 createdrop 等操作,在数据库中创建新表或删除表(create table或 drop table)

          数据操作语句(DML:Data Manipulation Language):包括insert、update、delete等操作,分别用于添加、修改、删除表中的数据
          数据查询语句(DQL:Data Query Language):可以用于查询获得表中的数据,关键字select是DQL(也是所有SQL)用得最多的操作,其他DQL常用的关键字有where,order by,group by和havin

    三、iOS的数据库技术的实现

      1>. 打开/关闭数据库

      ①. 创建或打开数据库

        · sqlite3_open() 将根据文件路径打开数据库,如果不存在,则会创建一个新的数据库。

        · 如果result等于常量SQLITE_OK,则表示成功打开数据库。

        · sqlite3 *db:一个打开的数据库实例。

        · 数据库文件的路径必须以C语言字符串(而非NSSString)传入。

      代码如下:

    //创建一个数据库指针作为单例,防止重复打开关闭
    static sqlite3 *db = nil;
    
    // 打开数据库
    + (sqlite3 *)open {
        // 此方法的主要作用是打开数据库,准确的说是连接数据库
        // 返回值是一个数据库指针
        // 因为,这个数据库在很多的SQLitr API(函数)中都会使用到,我们声明一个类方法来获取,更加方便
        if (db != nil) {
            return db;
        }
        // 获取Documents路径
        NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // 生成数据库文件在沙盒的路径
        NSString *sqlPath = [docPath stringByAppendingPathComponent:@"studb.sqlite"];
        // 获取文件管理对象
        NSFileManager *fileManager = [NSFileManager defaultManager];
        
        // 判断沙盒中是否存在数据库文件,如果存在就不执行拷贝操作,否则执行
        if ([fileManager fileExistsAtPath:sqlPath] == NO) {
            // 获取数据库文件在包中的路径
            NSString *filePath = [[NSBundle mainBundle] pathForResource:@"studb" ofType:@"sqlite"];
            // 使用文件管理对象,完成拷贝操作
            [fileManager copyItemAtPath:filePath toPath:sqlPath error:nil];
        }
        // 打开数据库 需要使用以下函数
        // 第一个参数是数据库路径,是一个C语言的字符串
        // 第二个参数是指向数据库指针的指针,保存数据库地址
        sqlite3_open([sqlPath UTF8String], &db);
        
        return db;
    }

      ②. 关闭数据库

       代码如下

    // 关闭数据库
    + (void)close {
        // 关闭数据库
        sqlite3_close(db);
        
        // 置空数据库指针
        db = nil;
    }
    // 单独创建一个DB类,继承自NSObject
    // 这个类主要是提供方法来操作数据库(打开和关闭数据库的方法)
    // 再我们的iOS工程中,一帮情况只有一个数据库,我们可以在数据库中创建多张表来保存不同的信息。
    // 但是千万不要创建多个数据库,每个数据库中只有一张表,因为不断的连接、关闭数据库是很耗性能的。

      2>. SQLite语法:常用系列函数

      ①. sqlite3_exec() 函数 可以执行任何SQL语句,比如建表、更新、插入、删除 操作。

        但是一般不用它执行查询语句,因为它不会返回查询到的数据。

        示例代码:创建表

    // 1、准备SQL语句
    NSString *sqlString  = "create table if not exists stu(s_id integer primary primary key autoincrement not null, s_name text, s_age integer)";
    
    // 2、执行SQL语句
    int result  = sqlite3_exec(db, sqlString.UTF8String, null, null, null);
    if (result == SQLITE_OK) {
        NSLog(@"建表成功!");
    } else {
        NSog(@"建表失败!");
    }

      ②. sqlite3_prepare() 函数

        sqlite3_prepare(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);

        参数:db:数据库指针

             zSql:SQL语句,使用UTF8编码;

             nByte:如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;

              如果nByte不是负的,那么它就是这个函数从zSql中读取的字节数的最大值。一般填 -1 ;

             pzTail:上面提到zSql在遇见终止符或者到达nByte之后结束,假如zSql还有剩余的内容就存放在pzTail中,

              不包括终止符;

             ppStmt:能够使用sqlite3_step() 函数 执行的编译好的准备语句的指针,如果发生错误,它被置为NULL。

      ③. sqlite3_bind_*() 函数(以 sqlite3_bind_text() 为例)

        sqlite3_bind_text(sqlite3_stmt *, int, const char *, int n, void (*)(void *))

        参数:sqlite3_stmt *:伴随指针

             int:参数序号(从1开始)

             const char *:参数值

             int n :参数长度

             void (*)(void *) :函数指针,SQLITE3执行完操作后调此函数,通常用于释放字符串占用的内存

      ④. sqlite3_column_* () 函数

        sqlite3_column_blob(sqlite3_stmt *, int iCol)

        参数:sqlite3_stmt *:从sqlite3_prepare返回来的prepare statement对象的指针

             int iCol:指定这一行中想要被返回的列的索引(从0开始)

      附表:常用函数功能

         

      3>. 具体实现的增删改查操作代码

      ①.获取所有数据方法(以一个Student 的数据库为例)

    // 获取表中保存的所有学生
    + (NSArray *)allStudents {
        // 查询需要使用Student语句
        // 不管对数据库进行什么操作,都需要连接数据库
        sqlite3 *db = [DB open];
        
        // 创建一个语句对象
        sqlite3_stmt *stmt = nil;
        
        // 声明数组对象
        NSMutableArray *mArr = nil;
        
        // 此函数的作用是生成一个语句对象,此时SQL语句并没有执行,创建的语句对象,保存了关键的数据库,执行的SQL语句,SQL语句的长度等信息
        int result = sqlite3_prepare_v2(db, "select * from Student", -1, &stmt, nil);
        if (result == SQLITE_OK) {
            // 为数组开辟空间
            mArr = [NSMutableArray arrayWithCapacity:0];
            
            // SQLITE_ROW仅用于查询语句,sqlite3_step()函数执行后的结果如果是SQLITE_ROW,说明结果集里面还有数据,会自动跳到下一条结果,如果是最后一条返回SQLITE_DONE,结束查询过程
            while (sqlite3_step(stmt) == SQLITE_ROW) {
                // 获取记录中的字段值
                // 第一个参数是语句对象,第二个参数是字段的下标,从0开始
                int ID = sqlite3_column_int(stmt, 0);
                const unsigned char *cName = sqlite3_column_text(stmt, 1);
                const unsigned char *cGender = sqlite3_column_text(stmt, 2);
                
                // 将获取到得C语言字符串转换成OC字符串
                NSString *name =[NSString stringWithUTF8String:(const char *)cName];
                NSString *gender =[NSString stringWithUTF8String:(const char *)cGender];
                Student *student = [Student studentWithID:ID name:name gender:gender];
                [mArr addObject:student];
            }
        }
        
        // 不管语句对象执行与否,释放语句队像
        sqlite3_finalize(stmt);
        
        return mArr;
    }

      ②. 查询数据

    // 根据指定ID,查找对应学生
    + (Student *)findStudentByID:(int)ID {
        // 打开数据库
        sqlite3 *db = [DB open];
        
        // 创建一个语句对象
        sqlite3_stmt *stmt = nil;
        
        Student *student = nil;
        
        int result = sqlite3_prepare_v2(db, "select * from Student where ID = ?", -1, &stmt, nil);
        if (result == SQLITE_OK) {
            // 如果查询语句或者其他SQL语句有条件,在准备语句对象的函数内部,SQL语句中用?来代替条件,那么在语句执行之前,一定要绑定
            // 1代表SQL语句中的第一个问号,下标从1 开始
            sqlite3_bind_int(stmt, 1, ID);
            
            if (sqlite3_step(stmt) == SQLITE_ROW) {
                
                // 获取记录中的字段信息
                const unsigned char *cName = sqlite3_column_text(stmt, 1);
                const unsigned char *cGender = sqlite3_column_text(stmt, 2);
                
                // 将C语言字符串转换成OC字符串
                NSString *name = [NSString stringWithUTF8String:(const char *) cName];
                NSString *gender = [NSString stringWithUTF8String:(const char *) cGender];
                student  = [Student studentWithID:ID name:name gender:gender];
            }
        }
        // 先释放语句对象
        sqlite3_finalize(stmt);
        return student;
    }

      ③. 增加一条数据

    // 插入一条记录
    + (void)insertStudentWithID:(int)ID name:(NSString *)name gender:(NSString *)gender {
        // 打开数据库
        sqlite3 *db = [DB open];
        
        // 创建一个语句对象
        sqlite3_stmt *stmt = nil;
        
        int result = sqlite3_prepare_v2(db, "insert into Student values(?, ?, ?)", -1, &stmt, nil);
        if (result == SQLITE_OK) {
            // 绑定问号
            sqlite3_bind_int(stmt, 1, ID);
            sqlite3_bind_text(stmt, 2, [name UTF8String], -1, nil);
            sqlite3_bind_text(stmt, 3, [gender UTF8String], -1, nil);
            // 插入与查询不一样,执行结果没有返回值
            sqlite3_step(stmt);
        }
        // 释放语句对象
        sqlite3_finalize(stmt);
    }

      ④. 修改一条数据

    // 更新指定ID的姓名和性别
    + (void)updateStudentName:(NSString *)name gender:(NSString *)gender forID:(int)ID {
        // 打开数据库
        sqlite3 *db = [DB open];
        
        // 创建一个语句对象
        sqlite3_stmt *stmt = nil;
        
        int result = sqlite3_prepare_v2(db, "update Student set name = ?, gender = ? where ID = ?", -1, &stmt, nil);
        if (result == SQLITE_OK) {
            // 绑定问号
            sqlite3_bind_text(stmt, 1, [name UTF8String], -1, nil);
            sqlite3_bind_text(stmt, 2, [gender UTF8String], -1, nil);
            sqlite3_bind_int(stmt, 3, ID);
            
            sqlite3_step(stmt);
            
        }
        // 释放语句对象
        sqlite3_finalize(stmt);
    }

      ⑤. 删除一条数据

    // 根据指定ID删除学生
    + (void)deleteStudnetByID:(int)ID {
        // 打开数据库
        sqlite3 *db = [DB open];
        
        // 创建一个语句对象
        sqlite3_stmt *stmt = nil;
        
        int result = sqlite3_prepare_v2(db, "delete from Student where ID = ?", -1, &stmt, nil);
        if (result == SQLITE_OK) {
            // 绑定问号
            sqlite3_bind_int(stmt, 1, ID);
            
            sqlite3_step(stmt);
        }
        // 释放语句对象
        sqlite3_finalize(stmt);
    }
    // 注:将对数据的具体操作方法,写到与表关联的模型类里面,这样让功能更加独立,代码更加清晰
  • 相关阅读:
    Hibernate框架—简介
    ooad单例模式-Singleton
    About-JavaOOAD
    win10内置ubuntu,mysql完美清理,并安装
    VUE关于对象动态添加属性无法双向绑定问题
    正则留档
    centos下tomcat中文路径不识别
    web服务器解释html-include
    rose
    聊天框突出箭头
  • 原文地址:https://www.cnblogs.com/hyl2012/p/5232728.html
Copyright © 2011-2022 走看看