SQLite

SQLite

一、简介

SQLite是一款轻型的嵌入式数据库,占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了,处理速度很快。数据库的存储结构和excel很像,以表(table)为单位。

学习在iOS中使用SQLite之前,最好先学会SQL语句,SQL中的常用关键字有
select、insert、update、delete、from、create、where、desc、order、by、group、table、alter等等。

这里不介绍SQL,如果需要学习的请直接移步w3cSchool。这里直接上代码,介绍在iOS中使用SQLite的方法。

二、基本使用方法

使用sqlite需要现在项目中导入libsqlite3.dylib,并在程序文件中导入sqlite3.h头文件。

2.1创建数据库/表

sqlite3 *_db;   //数据库

    //获取数据库文件路径
    NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *sqlitePath = [doc stringByAppendingPathComponent:@"student.sqlite"];

    //打开数据库,如果数据库文件不存在,程序会自动创建
    int result = sqlite3_open(sqlitePath.UTF8String, &_db);
    if (result == SQLITE_OK) {
        NSLog(@"成功打开数据库");

        const char *sql = "create table if not exists t_student (id integer primary key autoincrement, name text, age integer);";

        char *error = NULL;
        int result = sqlite3_exec(_db, sql, NULL, NULL, &error);

        if (result == SQLITE_OK) {
            NSLog(@"成功创建表student");
        }else {
            NSLog(@"创建表失败");
        }
    }else{
        NSLog(@"打开数据库失败");
    }

2.2 增删改

2.2.1 插入操作

- (IBAction)insertBtnClick:(id)sender {

        NSString *sql = [NSString stringWithFormat:@"insert into t_student (name, age) values('jack', 10);"];

        char *error = NULL;
        int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &error);

        if (result == SQLITE_OK) {
            NSLog(@"插入成功");
        }else{
            NSLog(@"插入失败");
        }
    }

}

2.2.2 更新操作

- (IBAction)updateBtnClick:(id)sender {

    //把年龄为10的学生姓名更改为mike
    NSString *sql = [NSString stringWithFormat:@"update t_student set name='mike' where and age=10"];
    char *error = NULL;
    int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &error);



}

2.2.3 删除操作

- (IBAction)deleteBtnClick:(id)sender {
    //一次性删除表中的全部数据,如果要删除某条数据,可以使用where关键字
    const char *sql = "delete from t_student;";
    char *error = NULL;
    int result = sqlite3_exec(_db, sql, NULL, NULL, &error);
}

通过上面的代码可以看出,增删改操作的步骤基本上只有2步:

  1. 编写SQL语句(const char * 类型,或NSString.UTF8String)
  2. 执行(sqlite3_exec)

2.3 查询操作

查询可以说是数据库管理中最重要的一个操作,因此单独拿出来讲。

- (IBAction)queryBtnClick:(id)sender {

    const char *sql = "select id, name, age from t_student s where s.name like ? and s.age > 20;";

    //存放查询结果集
    sqlite3_stmt *stmt = NULL;

    //检测查询语句的合法性
    //第三个参数表示查询语句的最大长度,设为-1程序会自动计算
    int result = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"查询语句是合法的");

        //设置占位符(也就是上面sql语句中的问号-?)的内容
        //%是sql中的通配符之一,在这里使用需要连续写两个%%,程序才会理解为sql中的通配符
        //%%mike%%表示查询条件为名字中间含有mike即可,前面和后面的值不管
        //如果占位符的值为int类型,则使用sqlite3_bind_int
        sqlite3_bind_text(stmt, 1, "%%mike%%", -1, NULL);

        //查询到一行数据
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            //获取第0、1、2列的数据
            int sid = sqlite3_column_int(stmt, 0);
            const unsigned char *sname = sqlite3_column_text(stmt, 1);
            int sage = sqlite3_column_int(stmt, 2);

            NSLog(@"查询成功-->%d, %s, %d", sid, sname, sage);

            if (sqlite3_step(stmt) == SQLITE_DONE) {
                NSLog(@"查询完毕");
            }

        }

        //不需要stmt的时候就把它释放
        sqlite3_finalize(stmt);
    }else {
        NSLog(@"查询失败");
    }

}

一般情况下,查询语句的编写都使用占位符赋值,而不是接收传过来的参数后直接赋值,这是因为SQL有一个漏洞叫注入漏洞。比如一个人要输入一个帐号密码来登录某个系统,他可以这么做:

帐号: 123 ’ or 1 = 1 or ’ ’ = ’
密码:(随便写一个)123456

则在程序中,查询语句就会变成这样:

select * from t_user where account='123' or 1 = 1 or ' ' = ' ' and password='123456';

所以,为了解决这个问题,查询语句一般都先使用占位符,之后再进行赋值。

2.4 计数

    //查询t_student中的行数
    int count = 0;
    const char *sql_count = "select count(*) from t_student";
    sqlite3_stmt *stmt2 = NULL;
    int result2 = sqlite3_prepare_v2(_db, sql_count, -1, &stmt2, NULL);
    if (result2 == SQLITE_OK) {

        if (sqlite3_step(stmt2) == SQLITE_ROW) {
            count = sqlite3_column_int(stmt2, 0);
            NSLog(@"查询完毕");
        }

        sqlite3_finalize(stmt2);
        NSLog(@"%d", count);
    }

三、多表关联

3.1 开启外键

SQLite中,外键是默认关闭的,如果要开启,则应该执行下面这条语句。

sqlite3_exec(_db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);

且每次连接(操作)数据库时,如果需要使用外键的功能,都需要执行这条语句。

3.2 创建关联的两个表

const char *sql_stu = 
"create table if not exists t_student (id integer primary key autoincrement, name text not null, age integer, class_id integer, constraint fk_t_student_class_id_t_class_id foreign key(class_id) references t_class(id) on delete cascade on update cascade);";

const char *sql_class = 
"create table if not exists t_class (id integer primary key autoincrement, name text not null unique);";

上面sql_stu的最后一句的意思是,创建一个名为 fk_t_student_class_id_t_class_id 的外键约束,把表t_student中的”class_id”和表t_class中的”id”关联起来。on delete cascade的意思是级联删除,比如说表t_student中某一行数据的calss_id为11,如果表t_class中id为11的数据被删除,则表t_student中calss_id为11的那行数据也会被删除。on update cascade同理。

3.3 插入测试数据

for(int i=0; i<20; i++){
    NSString *sql_stu = [NSString stringWithFormat:
    @"insert into t_student (name, age, class_id) values('jack-%d', %d, %d);", i+1, i+10, i+1]; NSString *sql_class = [NSString stringWithFormat: @"insert into t_class (name) values('computer science-%d');", i+1];
}

3.4 更新数据

//把class表中id为12的改为30,测试级联更新
sqlite3_exec(_db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);
NSString *sql_class = [NSString stringWithFormat:@"update t_class set id=%d where id=%d", 30, 12];

执行上面的代码,t_student表中class_id为12的也更新为30.

3.5 查询数据

const char *sql = 
"select s.id, s.name, s.age, c.name from (t_student s inner join t_class c on s.class_id = c.id) where s.name like ? and c.name like ? order by s.age desc;";
......//后面的步骤一样

四、小结

如果学过SQL,那么在iOS中使用SQLite就不成问题了,唯一需要注意的是sql语句的编写,不要漏了逗号、分号或者括号,不要写错字母

打开数据库并创表的步骤分为以下4步:

  1. 获取数据库文件路径
  2. 打开数据库(sqlite3_open(sqlitePath.UTF8String, &_db))
  3. 编写sql语句(const char * 类型,或NSString.UTF8String)
  4. 执行(sqlite3_exec(_db, sql, NULL, NULL, &error))

插入、更新、删除则只需要上面4步中的最后两步。

而查询操作则分为以下6步:

  1. 编写sql语句
  2. 创建sqlite3_stmt,存放结果集
  3. 检测查询语句的合法性(sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL))
  4. 设置占位符的值(sqlite3_bind_text)
  5. 查询到数据(while (sqlite3_step(stmt) == SQLITE_ROW))
  6. 释放stmt(sqlite3_finalize(stmt))

以上。

你可能感兴趣的:(ios,数据库,增删改查,count,外键)