iOS的SQLite编程

作者: CoderLWG | 来源:发表于2017-08-16 13:36 被阅读59次

    1.什么是SQLite?

    SQLite是一款轻型的嵌入式数据库,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了, 它的处理速度比Mysql、PostgreSQL这两款著名的数据库都还快。

    2.数据库存储数据的步骤

    1.新建数据库文件
    2.新建一张表(table)
    3.添加多个字段(column,列,属性)
    4.添加多行记录(row,每行存放多个字段对应的值)

    3.理论基础

    1.表格组成: 行(记录)和列(属性)

    "属性" 是用来标识这一列应该存放什么
    "记录" 是用来存放一条数据

    2.属性类型

    blob 二进制类型
    integer 整型
    real浮点型
    text文本类型
    null 空

    3.主键

    主键(Primary Key,简称PK)用来唯一地标识某一条记录
    主键可以是一个字段或多个字段
    主键的设计原则:主键应当是对用户没有意义的,永远也不要更新主键,主键不应包含动态变化的数据,主键应当由计算机自动生成

    4.SQL中的常用关键字

    数据库中不可以使用关键字来命名表、字段
    select、insert、update、delete、from、create、where、desc、order、by、group、table、alter、view、index等等

    5.SQL语句的种类

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

    数据操作语句(DML:Data Manipulation Language)
    包括insert、delete、update等操作
    上面的3种操作分别用于添加、修改、删除表中的数据

    数据查询语句(DQL:Data Query Language)
    可以用于查询获得表中的数据
    关键字select是DQL(也是所有SQL)用得最多的操作
    其他DQL常用的关键字有where,order by,group by和having

    6.补充资料 http://www.phpstudy.net/e/sql/sql_intro.html

    4.DDL语句

    1.新建和打开数据库

    sqlite3_open(filePath, &database);

    2.创建table

    create table 表名 (字段名1 字段类型1, 字段名2 字段类型2, …) ;
    示例
    create table if not exists t_student (id integer, name text, age inetger, score real) ;
    说明:实际上SQLite是无类型的
    就算声明为integer类型,还是能存储字符串文本(主键除外)
    建表时声明啥类型或者不声明类型都可以,也就意味着创表语句可以这么写:
    create table t_student(name, age);
    为了保持良好的编程规范、方便程序员之间的交流,编写建表语句的时候最好加上每个字段的具体类型。

    3.删表

    drop table if exists 表名 ;

    4.修改表

    修改表名
    ALTER TABLE 旧表名 RENAME TO 新表名
    新增属性
    ALTER TABLE 表名 ADD COLUMN 列名 数据类型 限定符

    5.给字段添加约束

    简单约束
    不能为空
    not null :规定字段的值不能为null
    不能重复
    unique :规定字段的值必须唯一
    默认值
    default :指定字段的默认值
    示例
    create table t_student (id integer, name text not null unique, age integer not null default 1) ;
    name字段不能为null,并且唯一
    age字段不能为null,并且默认为1

    主键约束
    添加主键约束的原因?
    如果t_student表中就name和age两个字段,而且有些记录的name和age字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据
    良好的数据库编程规范应该要保证每条记录的唯一性,为此,增加了主键约束
    也就是说,每张表都必须有一个主键,用来标识记录的唯一性
    在创表的时候用primary key声明一个主键
    如果想要让主键自动增长(必须是integer类型),应该增加autoincrement

    create table t_student (id integer primary key autoincrement, name text, age integer) ;
    

    6.DML语句

    1.插入数据(insert)

    格式
    insert into 表名 (字段1, 字段2, …) values (字段1的值, 字段2的值, …) ;
    示例
    insert into t_student (name, age) values (‘sz’, 10) ;
    注意
    数据库中的字符串内容应该用单引号 ’ 括住

    2.更新数据(update)

    格式
    update 表名 set 字段1 = 字段1的值, 字段2 = 字段2的值, … ;
    示例
    update t_student set name = ‘wex’, age = 20 ;
    注意
    上面的示例会将t_student表中所有记录的name都改为wex,age都改为20

    3.删除数据(delete)

    格式
    delete from 表名 ;
    示例
    delete from t_student ;
    注意
    上面的示例会将t_student表中所有记录都删掉

    7.条件语句

    作用:
    如果只想更新或者删除某些固定的记录,那就必须在DML语句后加上一些条件
    条件语句的常见格式

    where 字段 = 某个值 ; // 不能用两个 =
    where 字段 is 某个值 ; // is 相当于 =
    where 字段 != 某个值 ;
    where 字段 is not 某个值 ; // is not 相当于 !=
    where 字段 > 某个值 ;
    where 字段1 = 某个值 and 字段2 > 某个值 ; // and相当于C语言中的 &&
    where 字段1 = 某个值 or 字段2 = 某个值 ; // or 相当于C语言中的 ||
    示例:
    将t_student表中年龄大于10 并且 姓名不等于wex的记录,年龄都改为 5
    update t_student set age = 5 where age > 10 and name != ‘wex’ ;
    删除t_student表中年龄小于等于10 或者 年龄大于30的记录
    delete from t_student where age <= 10 or age > 30 ;

    8.DQL语句

    格式
    select 字段1, 字段2, … from 表名 ;
    select * from 表名; // 查询所有的字段
    示例
    select name, age from t_student ;
    select * from t_student ;
    select * from t_student where age > 10 ; // 条件查询

    9.代码实现DML语句-Insert绑定参数

    准备语句(prepared statement)对象代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。

    操作历程

    1. 使用sqlite3_prepare_v2或相关的函数创建这个对象
      如果执行成功,则返回SQLITE_OK,否则返回一个错误码
    2. 使用sqlite3_bind_*()给宿主参数(host parameters)绑定值
      sqlite3_bind_text
      参数1: 准备语句
      参数2:绑定的参数索引 (从1开始)
      参数3:绑定的参数内容
      参数4:绑定的参数长度 (-1代表自动计算长度)
      参数5:参数的处理方式
      SQLITE_TRANSIENT 会对字符串做一个 copy,SQLite 选择合适的机会释放
      SQLITE_STATIC / nil 把它当做全局静态变量, 不会字符串做任何处理,如果字符串被释放,保存到数据库的内容可能不正确!
    3. 通过调用sqlite3_step() 一次或多次来执行这个sql
      对于DML语句, 如果执行成功, 返回SQLITE_DONE
      对于DQL语句, 通过多次执行获取结果集, 继续执行的条件是返回值 SQLITE_ROW
    4. 使用sqlite3_reset()重置这个语句,然后回到第2步,这个过程做0次或多次
    5. 使用sqlite3_finalize()销毁这个对象, 防止内存泄露
    const char *insertSQL = "insert into word_inf values(null,?,?)";
    sqlite3_stmt *stmt;
    //预编译SQL语句,stmt变量保存了预编译结果的指针
     int insertReasult = sqlite3_prepare_v2(database, insertSQL, -1, &stmt, NULL);
     //如果预编译成功
     if (insertReasult == SQLITE_OK) {
         // 为第一个?占位符绑定参数
       sqlite3_bind_text(stmt, 1, [word UTF8String], -1, NULL);
       // 为第二个?占位符绑定参数
       sqlite3_bind_text(stmt, 2, [detail UTF8String], -1, NULL);
       // 执行SQL语句
        sqlite3_step(stmt);
      }
    sqlite3_finalize(stmt);
    
    

    10.代码实现DQL语句

    实现查询到的数据转化为OC对象,并存储在数组中

     sqlite3 *database;
     sqlite3_open([[self dbPath] UTF8String], &database);
    const char *selectSQL = "select * from word_inf where word like ?";
    sqlite3_stmt *stmt;
            
    int queryReasult = sqlite3_prepare_v2(database, selectSQL, -1, &stmt, NULL);
    NSMutableArray *result = [NSMutableArray array];
    if (queryReasult == SQLITE_OK) {
         // 为第一个?占位符绑定参数
        sqlite3_bind_text(stmt, 1, [[NSString stringWithFormat:@"%%%@%%",key] UTF8String], -1, NULL);
    // 采用循环多次执行sqlite3_step()函数,并从中取出查询结果
       while (sqlite3_step(stmt) == SQLITE_ROW) {
        // 分别获取当前行的不同列的查询数据
        int word_id = sqlite3_column_int(stmt, 0);
        char *word = (char *)sqlite3_column_text(stmt, 1);
      char *detail = (char *)sqlite3_column_text(stmt, 2);
      FKWord *fkWord = [[FKWord alloc] initWithId:word_id word:[NSString stringWithUTF8String:word] detail:[NSString stringWithUTF8String:detail]];
       [result addObject:fkWord];
     }
    
    

    11.代码实现-事务

    概念

    事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,可以将逻辑相关的一组操作绑定在一起,保持数据的完整性。

    事务通常是以BEGIN TRANSACTION开始,以COMMIT TRANSACTION或ROLLBACK TRANSACTION结束。

    COMMIT表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束。

    ROLLBACK表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态。

    修改两条记录, 一个成功, 一个失败测试
    
       XMGSQLTool.shareInstance.beginTransaction()
    
       let result1 = Student.updateStudent("score = score - 10", condition: "name = 'zs'")
    
       let result2 = Student.updateStudent("score1 = score + 10", condition: "name = 'wex'")
    
       // 如果都执行成功再提交, 如果都不成功, 那就回滚
    if result1 && result2
     {
        XMGSQLTool.shareInstance.commitTransaction()
     }else
     {
      XMGSQLTool.shareInstance.rollBackTransaction()
     }
    

    最后附上demo,下载地址

    相关文章

      网友评论

        本文标题:iOS的SQLite编程

        本文链接:https://www.haomeiwen.com/subject/aijirxtx.html