了解SQL语句之后,今天我们就来学习如何在iOS开发中使用SQLite3来存储数据。在iOS中使用SQLite3,首先要添加库文件libsqlite3.dylib和导入主头文件。
直接上代码
新建项目:(做一个存储学生信息的简单例子)
向项目中添加库文件libsqlite3.tdb,并导入头文件。
在ViewController.m文件中导入头文件:#import <sqlite3.h>
搭建项目框架:
输入学生的姓名、年龄、性别(都不能为空)之后,点击添加按钮将该学生信息添加到数据库学生表中。
1. 在控制器view加载完毕后,创建数据库,并打开(先声明一个全局的数据库实例)。打开成功后,在数据库中创建一个学生表
<span style="color:#ff0000;">sqlite3 *_db;// 数据库实例</span>
- (void)viewDidLoad {
[super viewDidLoad];
// 控制器view加载完毕后,创建数据库
// 拼接数据库地址
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *sqlFilePath = [path stringByAppendingPathComponent:@"student.sqlite"];
// 将根据文件路径打开数据库,如果不存在,则会创建一个新的数据库。如果result等于常量SQLITE_OK,则表示成功打开数据库
int result = sqlite3_open(sqlFilePath.UTF8String, &_db);
if (result == SQLITE_OK) {// 打开成功
NSLog(@"数据库打开成功");
// 数据库打开成后,可以向数据库中创建表
// id:是主键,和学生信息无关,只是起到使学生记录唯一的作用
char *errorMsg = NULL; // 用来存储错误信息
char *sql = "create table if not exists t_student(id integer primary key autoincrement, name text, age integer, sex text);";
// sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。但是一般不用它执行查询语句,因为它不会返回查询到的数据
// sqlite3_exec()还可以执行的语句:
// 开启事务:begin transaction;
// 回滚事务:rollback;
// 提交事务:commit;
int result = sqlite3_exec(_db, sql, NULL, NULL, &errorMsg);
if (result == SQLITE_OK) {
NSLog(@"创表成功");
}else {
NSLog(@"创表失败%s", errorMsg);
}
}else {
NSLog(@"数据库打开失败");
}
}
运行结果:
会在沙盒中看到一个.sqlite文件
该文件可以使用一个叫Navicat的软件打开
2. 学生表创建完成后,就要向表中插入(添加)数据。添加自己录入的信息。则按钮的点击事件中如下:
/**
* 添加学生
*/
- (IBAction)addClick {
if ([self.nameTextField.text isEqualToString:@""]) {
NSLog(@"姓名不能为空");
return;
}
if ([self.ageTextField.text isEqualToString:@""]) {
NSLog(@"年龄不能为空");
return;
}
if ([self.sexTextField.text isEqualToString:@""]) {
NSLog(@"性别不能为空");
return;
}
// 数据库中得表创建完后,可以向表中插入数据(添加一个学生)
// 插入SQL语句(带占位符插入数据)
char *sql = "insert into t_student(name, age, sex) values(?, ?, ?);";
// sqlite3_prepare_v2()返回值等于SQLITE_OK,说明SQL语句已经准备成功,没有语法问题
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL) == SQLITE_OK) {
NSLog(@"SQL语句已经准备成功,没有语法问题");
sqlite3_bind_text(stmt, 1, self.nameTextField.text.UTF8String, -1, NULL);
sqlite3_bind_int(stmt, 2, [self.ageTextField.text intValue]);
sqlite3_bind_text(stmt, 3, self.sexTextField.text.UTF8String, -1, NULL);
NSLog(@"插入成功");
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
NSLog(@"插入数据错误");
}
// 销毁sqlite3_stmt *对象
sqlite3_finalize(stmt);
/*
sqlite3_bind_text():大部分绑定函数都只有3个参数
第1个参数是sqlite3_stmt *类型
第2个参数指占位符的位置,第一个占位符的位置是1,不是0
第3个参数指占位符要绑定的值
第4个参数指在第3个参数中所传递数据的长度,对于C字符串,可以传递-1代替字符串的长度
第5个参数是一个可选的函数回调,一般用于在语句执行后完成内存清理工作
sqlite_step():执行SQL语句,返回SQLITE_DONE代表成功执行完毕
sqlite_finalize():销毁sqlite3_stmt *对象
*/
}
添加一个学生:shx、28、male。点击添加按钮(使用Navicat查看)
3. 向学生表中插入多条学生信息(多条记录)
4. 删除学习信息,这里只做删除指定姓名的学生(该姓名必须在表中存在,后面将讲解查询学生信息的SQL语句)
/**
* 删除指定姓名的学生信息
*/
- (IBAction)deleteClick {
if ([self.deleteNameTextField.text isEqualToString:@""]) {
NSLog(@"要删除学生的姓名不能为空");
return;
}
// 删除SQL语句
NSString *sql = [NSString stringWithFormat:@"delete from t_student where name = '%s';", self.deleteNameTextField.text.UTF8String];
// 执行删除语句,并返回结果
char *errorMsg = NULL; // 用来存储错误信息
int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMsg);
if (result == SQLITE_OK) {
NSLog(@"删除成功");
}else {
NSLog(@"删除失败-%s", errorMsg);
}
}
运行结果:(所有叫shx的学生会全部被删除)
5. 更新某个学生的信息(修改某个学生的年龄)
/**
* 修改指定学生的年龄
*/
- (IBAction)tureClick {
if ([self.updataStudentTextField.text isEqualToString:@""]) {
NSLog(@"姓名不能为空");
return;
}
if ([self.updataAgeTextField.text isEqualToString:@""]) {
NSLog(@"年龄不能为空");
return;
}
// 更新SQL语句
NSString *sql = [NSString stringWithFormat:@"update t_student set age = %d where name = '%s';", [self.updataAgeTextField.text intValue], self.updataStudentTextField.text.UTF8String];
// 执行更新语句,并返回结果
char *errorMsg = NULL; // 用来存储错误信息
int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMsg);
if (result == SQLITE_OK) {
NSLog(@"更新成功");
}else {
NSLog(@"更新失败-%s", errorMsg);
}
}
运行结果:(所有叫rose的学生年龄会全部改成20)
修改前:
修改后:
/**
* 查询指定姓名的学生信息,并打印出来
*/
- (IBAction)queryClick {
if ([self.queryNameTextField.text isEqualToString:@""]) {
NSLog(@"姓名不能为空");
return;
}
//查询SQL语句
NSString *query = [NSString stringWithFormat:@"select * FROM t_student where name = '%@'", self.queryNameTextField.text];
// 准备语句
sqlite3_stmt *statement;
int queryResult = sqlite3_prepare_v2(_db, [query UTF8String], -1, &statement, nil);
//查询准备成功
if (queryResult == SQLITE_OK) {
//依次读取数据库表格t_student中每行的内容,并打印出来
while (sqlite3_step(statement) == SQLITE_ROW) {
//获得数据
// id
int ID = sqlite3_column_int(statement, 0);
// 姓名
char *name = (char*)sqlite3_column_text(statement, 1);
// 年龄
int age = sqlite3_column_int(statement, 2);
// 性别
char *sex = (char *)sqlite3_column_text(statement, 3);
// 打印
NSString *ocName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
NSString *ocSex = [NSString stringWithCString:sex encoding:NSUTF8StringEncoding];
NSLog(@"学生信息:id:%d,姓名:%@,年龄:%d,性别:%@", ID, ocName, age, ocSex);
}
// 销毁sqlite3_stmt *对象
sqlite3_finalize(statement);
}else {
NSLog(@"学生不存在");
}
//关闭数据库
sqlite3_close(_db);
}
运行结果:
通过上面的例子,我们来总结一下。
1. sqlite3_open函数:将根据文件路径打开数据库,如果不存在,则会自动创建一个新的数据库。如果返回result等于常量SQLITE_OK,则表示成功打开数据库。注意:sqlite3 *db:一个打开的数据库实例。数据库文件的路径必须以C字符串(而非NSString)传入
2. 每次执行数据库操作之前要打开数据库,使用完毕后要将数据库关闭:sqlite3_close(_db)
3. 执行不返回数据的SQL语句:sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。
注意:一般不用它来执行查询语句,因为它不会返回查询到的数据。
4. 绑定变量(带占位符的插入语句):可以使用绑定变量来执行数据库插入操作。正常创建SQL语句后,在SQL语句中用?号来替代你想绑定的值,一个?号代表一个值,然后准备SQL语句,将真实值绑定到各个变量,然后执行命令(如上面的添加操作)
常见的绑定函数:(绑定的索引从1开始)
sqlite3_bind_int(sqlite3_stmt *, int, int)
sqlite3_bind_text(sqlite3_stmt *, int, const char *, int n,void (*)(void *))
5. 准备SQL语句:sqlite3_prepare_v2(),其返回值等于SQLITE_OK说明传入的SQL语句已经准备成功,没有语法错误可以执行SQL语句。然后使用sqlite3_step()函数来单步调试结果,若结果返回SQLITE_DONE表示成功执行完毕。
6. 执行查询语句的时候,必须使用sqlite3_prepare_v2()来做准备。准备好后,执行sqlite_step()函数来遍历查询到的结果集。使用sqlite3_column_*()函数来取出对应列的字段。
7. 在执行sqlite3_prepare_v2()函数时候,准备好语句后,会返回一个sqlite3_stmt类型:数据库句柄(了解不深)数据。之后可操作该变量里的数据如查询的数据、绑定的数据。使用完之后,一定要销毁sqlite3_finalize()。
SQLit3数据库的基础知识就介绍都这里。