1.sqllite****好处1> 存储大批量数据,可以精确的读取数据。2> 批量读取数据,NSCoding这些都是一次把所有数据读取出来。
2.****数据库怎么存储1> 跟excel很像,以表为单位,每个表都是存储不同的数据。2> 存储学生数据步骤
• 先要创建表• 确定属性(字段)• 插入数据(记录)
3.****数据库专业术语:1> name,id这些叫字段
2> 一行叫做一个记录。4.利用Navcat工具演示数据库
1> 创建数据库,取数据库连接名,创建数据库文件,数据库是以文件存在的。2> 连接数据库,双击连接名,会自动创建一个名为main的数据库。
• table:数据库表
• view:视图2> 创建表格3> 添加字段,保存表格,表格名称以t_开头
text 字符串
integer 整形
real 浮点型
4> 主键:保证数据唯一性,区分相同的数据。主键:自动增长
5.sql****语句1> 为什么要学习sql语句,、以后数据库肯定是运行时创建的,我们不可能去用户的手机上装个navcat先创建好数据库,在存储。2> 想要操作数据库,就要学习sql语句,跟操作iOS,学习oc一样。PPT简介,主要学习增删查改(CRUD) 增加(Create)、读取(Retrieve)(重新得到数据)、更新(Update)和删除(Delete)3> SQL语句特点
• 不区分大小写4> SQL语句种类
DDL语句(数据定义语句:定义数据格式):创表和删表 creat和drop
DML语句(数据操作语句):增删查改 insert,delete,update,select• DQL语句(数据查询语句)
3> SQL语句特点
• 不区分大小写4> SQL语句种类
DDL语句(数据定义语句:定义数据格式):创表和删表 creat和drop
DML语句(数据操作语句):增删查改 insert,delete,update,select
DQL语句(数据查询语句)
6.DDL语句1> 创建表格
数据库表格是唯一的,创建表格的时候加上一句if not exists,不存在才需求创建,就不会报sql语句错误。
创建没有主键的key2>删除表格
• 删除没有主键的key
• 创建一个有主键的key,primary key,自动增长 autoincrement7.DML语句
1> 插入数据• 数据库字符串用单引号'
2> 更新数据3> 删除数据4> 条件语句
8.DQL语句1> select
2> 别名,可以不用as,• 给数据库取别名的好处:用别名获取字段,有提示。
3> 计算查询数量count4> 排序: 有条件语句,需要放在条件语句后。5> limit : limit 0,5 跳过第0个,取5个数据,意味着取前5个数据。这个语句必须放在查询语句最后面。
9.****通过代码访问数据库1> 导入系统自带框架sqlite32> 打开数据库,没有创建数据库,会自动创建,并且返回数据库实例3>增删改4> 查,不能用exec,因为exec执行完就没了,不会返回数据。
查询数据,首先要做一些准备操作,获取stmt句柄,有了句柄就能拿到数据了
调用step,执行stmt,通过stmt能查询下一条数据
stmt:是一行一行往下提取,用while判断是否还有数据,如果没有
数据,就不会返回SQLITE_ROW.
根据stmt获取每条记录的字段值
10.数据库的封装
要变成模型,展示到视图。
2> 搞个专门的工具类处理数据库的逻辑。11.模糊查询
1> 通常开发中,面向模型开发,也就是把模型保存到数据库,取出来也要变成模型,展示到视图。
• 根据stmt获取每条记录的字段值10.数据库的封装
• %:通配符表示任意1> 搞个搜索框,输入条件,展示数据2> 添加按钮,插入100条数据,并且保存到数据库3> 封装工具类进行模糊查询
sqlite3是轻量级嵌入式数据库、C源代码,完全开放。
掌握常用的SQL语句:
创建表:"create table if not exists 表名(id intager primary key, 数据对象1 对象类型text,数据对象2 对象类型BLOB)"
添加数据:"insert into 表名 values(null,?,?)"
删除数据 : "delete from 表名 where intTeger = ?"
修改数据: "update 表名 set 数据对象1 = ?,数据对象2 = ? where intTeger"
查询获取数据:"select *from 表名"
掌握SQLite3的使用及常用函数的作用
导入libsqlite3.dylib库并添加头文件#import
数据库连接指针:sqlite3*
打开数据库:int sqlite3_open(const char *fileName, sqlite3 **ppDb);
创建SQL语句预编译指针:sqlite3_stmt *
预编译SQL语句:int sqlite3_prepare[prepare_v2](sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail);
绑定SQL语句占位符:int sqlite3_bind_xxx
执行预编译的SQL语句:int sqlite3_step(sqlite3_stmt *)
获取数据表中数据:sqlite3_column_xxx(sqlite3_stmt *,int iCol);
销毁预编译指针:int sqlite3_finalize(sqlite3_stmt *pStmt)
关闭数据库:int sqlite3_close(sqlite3 *db)
创建一个Demo工程,可以使用SQLite3实现数据的增、删、改、查
第三方:MBProgressHUD(提示框)
Project.pch
#ifndef Project_pch
#define Project_pch
// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
#import "MBProgressHUD.h"
#import "User.h"
#endif /* Project_pch */
AppDelegate.m
#import "AppDelegate.h"
#import "ShowViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
ShowViewController *showVc = [[ShowViewController alloc]init];
showVc.navigationItem.title = @"全部用户";
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:showVc];
self.window.rootViewController = nav;
return YES;
}
首先先创建数据对象类
User.h
#import
@interface User : NSObject
@property (nonatomic,strong)NSString *phone;
@property (nonatomic,strong)NSString *password;
@property (nonatomic,strong)NSString *name;
@property (nonatomic,assign)NSInteger ID;
@end
User.m
#pragma mark - NSCopy
//方法1 无需协议
- (id)copy
{
User *u = [[User alloc]init];
u.phone = self.phone;
u.name = self.name;
u.password = self.password;
u.ID = self.ID;
return u;
}
//方法2
//浅复制
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
创建业务处理层
SQLiteDataBase.h
#import
@interface SQLiteDataBase : NSObject
//创建表
- (BOOL)creatTableByName:(NSString *)name;
+(instancetype)defaultDataBase;
///添加
- (BOOL)addNew:(id)newObj;
///删除
- (BOOL)deleteOne:(id)deleteobj;
///修改
- (BOOL)updataOne:(id)upObj;
///获取所有
- (id)getAllObjects;
@end
SQLiteDataBase.m
#import "SQLiteDataBase.h"
#import
#define USER_PATH @"users.db" //数据库文件的名称
static SQLiteDataBase *_dataBase = nil;
//延展
@interface SQLiteDataBase()
{
sqlite3 *_db; // 操作数据库内存的指针
NSString *_tableName; //表名字符串
}
@end
@implementation SQLiteDataBase
#pragma mark -单例类的方法
//重写allocWithZone方法,让外部文件使用alloc方法创建对象时,只得到一块内存空间
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
if (_dataBase == nil)
{
_dataBase = [super allocWithZone:zone];
}
return _dataBase;
}
+(instancetype)defaultDataBase
{
if (_dataBase == nil)
{
_dataBase = [[SQLiteDataBase alloc]init];
}
return _dataBase;
}
- (id)copy
{
return self;
}
- (id)mutableCopy
{
return self;
}
#pragma mark - 私有方法
//打开数据库
- (BOOL)openDB:(NSString *)dbPath
{
//打开数据库
//如果数据库文件不存在,先创建再打开,如果存在,直接打开
//参数1 - 持久化文件的路径字符串
NSString *fPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:dbPath];
NSLog(@"db文件%@",fPath);
int res = sqlite3_open(fPath.UTF8String, &_db);
if (res == SQLITE_OK)
{
return YES;
}
else
return NO;
}
///关闭数据库
- (void)closeDB
{
sqlite3_close(_db);
}
///创建一个数据表
- (BOOL)creatTableByName:(NSString *)name
{
_tableName = name;
BOOL success = [self openDB:USER_PATH];
if (!success) {
[self closeDB];
return NO;
}
//执行创建数据表操作
// 1)先做一个sql语句
//UNIQUE 唯一约束 PRIMARY KEY 主键自增
NSString *sql = [NSString stringWithFormat:@"CREATE TABLE %@ (id INTEGER PRIMARY KEY AUTOINCREMENT,phone TEXT UNIQUE,name TEXT,password TEXT)",name];
//2)定义一个预编译指针,用于存储编译结果
sqlite3_stmt *statement = NULL;
//3)执行编译操作,将sql语句转换为机器可以读懂的机器码
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &statement,NULL);
//4)执行编译结果
int res = sqlite3_step(statement);
//5)释放预编译指针指向的内存
sqlite3_finalize(statement);
//关闭数据库
[self closeDB];
return res == SQLITE_DONE ? YES :NO;
}
#pragma mark - 对外公开的方法
///添加
- (BOOL)addNew:(User *)newObj
{
if (![self openDB:USER_PATH])
{
[self closeDB];
return NO;
}
// 1)先做一个sql语句
NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ (phone,name,password) VALUES (?,?,?)",_tableName];
//2)定义一个预编译指针,用于存储编译结果
sqlite3_stmt *statement = NULL;
//3)执行编译操作,将sql语句转换为机器可以读懂的机器码
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &statement,NULL);
//4)绑定?号
//参数1 - 预编译指针变量
//参数2 - 第几个问号
//参数3 - 绑定的数据
//参数4 - 读取绑定数据的前几个字符,-1表示全部内容
//参数5 - 短暂,固定两个选择
sqlite3_bind_text(statement, 1, newObj.phone.UTF8String, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, newObj.name.UTF8String, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, newObj.password.UTF8String, -1, SQLITE_TRANSIENT);
//4)执行编译结果
int res = sqlite3_step(statement);
//5)释放预编译指针指向的内存
sqlite3_finalize(statement);
//关闭数据库
[self closeDB];
return res == SQLITE_DONE ? YES :NO;
}
///删除
- (BOOL)deleteOne:(User *)deleteobj
{
if (![self openDB:USER_PATH])
{
[self closeDB];
return NO;
}
NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE id = ?",_tableName];
//2)定义一个预编译指针,用于存储编译结果
sqlite3_stmt *statement = NULL;
//3)执行编译操作,将sql语句转换为机器可以读懂的机器码
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &statement,NULL);
sqlite3_bind_int(statement, 1, (int)deleteobj.ID);
//4)执行编译结果
int res = sqlite3_step(statement);
//5)释放预编译指针指向的内存
sqlite3_finalize(statement);
//关闭数据库
[self closeDB];
return res == SQLITE_DONE ? YES :NO;
}
///修改
- (BOOL)updataOne:(User *)upObj
{
if (![self openDB:USER_PATH])
{
[self closeDB];
return NO;
}
NSString *sql = [NSString stringWithFormat:@"UPDATE %@ SET name = ?,password = ? WHERE id = ?",_tableName];
//2)定义一个预编译指针,用于存储编译结果
sqlite3_stmt *statement = NULL;
//3)执行编译操作,将sql语句转换为机器可以读懂的机器码
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &statement,NULL);
sqlite3_bind_text(statement, 1, upObj.name.UTF8String, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, upObj.password.UTF8String,-1, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 3, (int)upObj.ID);
//4)执行编译结果
int res = sqlite3_step(statement);
//5)释放预编译指针指向的内存
sqlite3_finalize(statement);
//关闭数据库
[self closeDB];
return res == SQLITE_DONE ? YES :NO;
}
///获取所有
- (id)getAllObjects
{
if (![self openDB:USER_PATH])
{
[self closeDB];
return nil;
}
// 1)先做一个sql语句
NSString *sql = [NSString stringWithFormat:@"SELECT *FROM %@",_tableName];
//2)定义一个预编译指针,用于存储编译结果
sqlite3_stmt *statement = NULL;
//3)执行编译操作,将sql语句转换为机器可以读懂的机器码
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &statement,NULL);
//4)每行每行的读取数据
NSMutableArray *arr = [[NSMutableArray alloc]init];
while (sqlite3_step(statement) == SQLITE_ROW)
{
int ID = sqlite3_column_int(statement, 0);
const char *phone = (const char *)sqlite3_column_text(statement, 1);
const char *name = (const char *)sqlite3_column_text(statement, 2);
const char *pwd = (const char *)sqlite3_column_text(statement, 3);
User *u = [[User alloc]init];
u.ID = ID;
u.phone = [NSString stringWithUTF8String:phone];
u.name = [NSString stringWithUTF8String:name];
u.password = [NSString stringWithUTF8String:pwd];
[arr addObject:u];
}
//5)释放预编译指针指向的内存
sqlite3_finalize(statement);
//关闭数据库
[self closeDB];
return arr;
}
@end
ShowViewController.h
#import
@interface ShowViewController : UIViewController
@end
ShowViewController.m
#import "ShowViewController.h"
#import "AddViewController.h"
#import "User.h"
#import "DetailViewController.h"
#import "SQLiteDataBase.h"
@interface ShowViewController ()
{
NSMutableArray *_tableDataArr; //表格赋值数组
}
@property (nonatomic,strong)UITableView *tableView;
@property (nonatomic,strong)AddViewController *addVc;
@property (nonatomic,strong)DetailViewController *detailVc;
@property (nonatomic,strong)id db; //数据库对象
@end
@implementation ShowViewController
#pragma mark - 懒加载 ,属性getter重写
- (UITableView *)tableView
{
if (!_tableView)
{
_tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
_tableView.delegate =self;
_tableView.dataSource = self;
}
return _tableView;
}
- (AddViewController *)addVc
{
if (!_addVc)
{
_addVc = [[AddViewController alloc]init];
}
return _addVc;
}
- (DetailViewController *)detailVc
{
if (!_detailVc)
{
_detailVc = [[DetailViewController alloc]init];
}
return _detailVc;
}
- (id)db
{
if (!_db)
{
_db = [[SQLiteDataBase alloc]init];
[_db creatTableByName:@"users"];
}
return _db;
}
//添加子视图
- (void)loadView
{
[super loadView];
//
NSLog(@"%@",NSStringFromSelector(_cmd));
[self.view addSubview:self.tableView];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addDidHandle:)];
}
- (void)addDidHandle:(id)sender
{
[self.navigationController pushViewController:self.addVc animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%@",NSStringFromSelector(_cmd));
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
_tableDataArr = [self.db getAllObjects];
[self.tableView reloadData];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _tableDataArr.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifer = @"CELL";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer];
if (!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifer];
}
User *u = _tableDataArr[indexPath.row];
cell.textLabel.text = u.phone;
cell.detailTextLabel.text = [NSString stringWithFormat:@"ID:%ld名字:%@密码:%@",u.ID,u.name,u.password];
return cell;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
//删除底层数据
[self.db deleteOne:_tableDataArr[indexPath.row]];
//删除给表格赋值的数组中相对应的数据
[_tableDataArr removeObjectAtIndex:indexPath.row];
//删除单元格
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView reloadData];
}
}
#pragma mark----UITableViewDelegate----
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.detailVc.passUser = _tableDataArr[indexPath.row];
[self.navigationController pushViewController:self.detailVc animated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
AddViewController.h
#import
@interface AddViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *phoneTF;
@property (weak, nonatomic) IBOutlet UITextField *pwdTF;
@property (weak, nonatomic) IBOutlet UITextField *nameTF;
- (IBAction)saveHandle:(id)sender;
@end
AddViewController.m
#import "AddViewController.h"
#import "User.h"
#import "SQLiteDataBase.h"
@interface AddViewController ()
{
MBProgressHUD *_hud;
}
@end
@implementation AddViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
_hud = [[MBProgressHUD alloc]init];
[self.view addSubview:_hud];
[_hud hide:YES];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.phoneTF.text = @"";
self.pwdTF.text = @"";
self.nameTF.text= @"";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)saveHandle:(id)sender {
if (self.phoneTF.text.length == 0 || self.pwdTF.text.length == 0 || self.nameTF.text.length == 0)
{
//设置弹出框的样式
_hud.mode = MBProgressHUDModeText;
//设置提示文本
_hud.labelText = @"输入的内容不能为空";
//显示
[_hud show:YES];
//2秒后隐藏
[_hud hide:YES afterDelay:2.0];
return;
}
id db = [[SQLiteDataBase alloc]init];
User *u = [[User alloc]init];
u.phone = self.phoneTF.text;
u.password = self.pwdTF.text;
u.name = self.nameTF.text;
BOOL success = [db addNew:u];
if (success) {
//设置弹出框的样式
_hud.mode = MBProgressHUDModeText;
//设置提示文本
_hud.labelText = @"添加成功!";
//显示
[_hud show:YES];
[self performSelector:@selector(back:) withObject:nil afterDelay:2.0];
}
else
{
//设置弹出框的样式
_hud.mode = MBProgressHUDModeText;
//设置提示文本
_hud.labelText = @"用户已存在!";
//显示
[_hud show:YES];
//2秒后隐藏
[_hud hide:YES afterDelay:2.0];
}
}
- (void)back:(id)sender
{
if (_hud.isHidden == NO)
{
[_hud hide:YES];
}
[self.navigationController popViewControllerAnimated:YES];
}
@end
AddViewController.xib
DetailViewController.h
#import
@interface DetailViewController : UIViewController
@property (nonatomic,strong)User *passUser;
@end
DetailViewController.m
#import "DetailViewController.h"
#import "SQLiteDataBase.h"
@interface DetailViewController ()
@property (weak, nonatomic) IBOutlet UITextField *phoneTF;
@property (weak, nonatomic) IBOutlet UITextField *pwdTF;
@property (weak, nonatomic) IBOutlet UITextField *nameTF;
- (IBAction)updataHandle:(id)sender;
@end
@implementation DetailViewController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.phoneTF.text = self.passUser.phone;
self.pwdTF.text= self.passUser.password;
self.nameTF.text = self.passUser.name;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)updataHandle:(id)sender {
// User *newU = [[User alloc]init];
//
// newU.ID = self.passUser.ID;
// newU.phone = self.passUser.phone;
// newU.password = self.pwdTF.text;
// newU.name = self.nameTF.text;
//这句话实现与上面4句代码等效的结果
User *newU = [self.passUser copy];
newU.password = self.pwdTF.text;
newU.name = self.nameTF.text;
SQLiteDataBase *db = [[SQLiteDataBase alloc]init];
BOOL success = [db updataOne:newU];
MBProgressHUD *hud = [[MBProgressHUD alloc]initWithView:self.view];
[self.view addSubview:hud];
hud.removeFromSuperViewOnHide = YES;
hud.mode = MBProgressHUDModeText;
hud.labelText = success ? @"更新成功" :@"更新失败";
[hud show:YES];
[hud hide:YES afterDelay:2.0];
}
@end
DetailViewController.xib