1、數據持久化概述php
數據持久化就是數據的永久存儲。其本質是將數據保存爲文件,存到程序的沙盒中。html
一、數據持久化的方式web
1.1 writeToFile:簡單對象寫入文件sql
1.2 NSUserDefaults:應用程序偏好設置
1.3 Sqlite:輕量級關係型數據庫,不能直接存儲對象(NSData除外),須要用到一些SQL語句,先將複雜對象歸檔(對象->NSData)數據庫
1.4 CoreData:對象型數據庫,實質是將數據庫的內部存儲細節封裝數組
1.5 Plist文件緩存
二、應用程序沙盒app
每一應用程序都有本身的應用沙盒,沙盒的本質就是一個文件夾,名字是隨機分配的。框架
與其餘應用程序沙盒隔離,應用程序自己只能訪問本身沙盒的數據。(iOS8+對沙盒之間的訪問部分開放)工具
2.1 應用程序包(.app)
包含了應用程序中所用到的全部資源文件和可執行文件(Base on Unix)。iOS8時,app不存儲在沙盒中,有單獨的文件夾存儲全部程序的app包。
2.2 HomeDirectory
Documents:保存應用運行時生成的須要持久化的數據,iTunes同步設備時會備份該目錄。例如,遊戲應用可將遊戲存檔保存在該目錄
tmp:保存應用運行時所需的臨時數據,使用完畢後再將相應的文件從該目錄刪除。應用沒有運行時,系統也可能會清除該目錄下的文件。iTunes同步設備時不會備份該目錄
Library/Caches:保存應用運行時生成的須要持久化的數據,iTunes同步設備時不會備份該目錄。通常存儲體積大、不須要備份的非重要數據
Library/Preference:保存應用的全部偏好設置,iOS的Settings(設置)應用會在該目錄中查找應用的設置信息。iTunes同步設備時會備份該目錄
2.3 獲取沙盒路徑
沙盒根目錄: NSHomeDirectory();
沙盒臨時目錄:NSTemporaryDirectory();
Library/Preferences:NSUserDefaults
//1.獲取沙盒中Documents文件夾的路徑
//第一種方式:
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject; //NO, path = @"~/"(相對路徑); YES 絕對路徑
NSLog(@"%@", documentPath);
//第二種方式: (不建議採用,由於新版本的操做系統可能會修改目錄名)
NSString *homePath = NSHomeDirectory();
NSString *documentPath2 = [homePath stringByAppendingPathComponent:@"library/caches"];
NSLog(@"%@", documentPath2);
//2.獲取應用程序包路徑(.app)
NSLog(@"%@", [NSBundle mainBundle].resourcePath);
2、簡單對象持久化
一、簡單對象
NSString\NSArray\NSDictionary\NSData
使用writeToFile:方法,將數據存儲爲.plist文件
atomically參數爲是否寫入緩存
//字符串
NSString *string = @"I U";
//數組
NSArray *array = @[@"張三", @"李四", @"王五"];
//字典
NSDictionary *dictionary = @{@"name":@"張三", @"age":@"20", @"sex":@"男"};
//NSData
UIImage *image = [UIImage imageNamed:@"1.jpg"];
NSData *data = UIImageJPEGRepresentation(image, 1);
//1.拼接存儲路徑
NSString *strPath = [documentPath stringByAppendingPathComponent:@"string.txt"];
NSString *arrayPath = [documentPath stringByAppendingPathComponent:@"array.txt"];
NSString *dicPath = [documentPath stringByAppendingPathComponent:@"dict.txt"];
NSString *dataPath = [documentPath stringByAppendingPathComponent:@"data.txt"];
//2.寫入文件
[string writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
[array writeToFile:arrayPath atomically:YES];
[dictionary writeToFile:dicPath atomically:YES];
[data writeToFile:dataPath atomically:YES];
//3.讀取文件內容
NSString *fileString = [NSString stringWithContentsOfFile:strPath encoding:NSUTF8StringEncoding error:nil];
NSArray *fileArray = [NSArray arrayWithContentsOfFile:arrayPath];
NSDictionary *fileDict = [NSDictionary dictionaryWithContentsOfFile:dicPath];
NSData *fileData = [NSData dataWithContentsOfFile:dataPath];
NSLog(@"%@", fileString);
NSLog(@"%@", fileArray);
NSLog(@"%@", fileDict);
NSLog(@"%@", fileData);
二、文件管理類:NSFileManager
2.一、功能
NSFileManager使用defaultManager建立單例對象。能夠建立文件夾,能夠刪除、移動、建立文件,判斷文件是否存在。
2.二、使用
//緩存文件夾所在路徑
NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
NSLog(@"%@", cachesPath);
//在cachesPath路徑下建立一個文件夾
NSString *directoryPath = [cachesPath stringByAppendingPathComponent:@"path"];
NSFileManager *fileManager = [NSFileManager defaultManager]; //建立文件管理類單例對象
//根據路徑建立文件夾
NSDictionary *fileDate = @{@"createTime":@"2015-9-9"};
[fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:fileDate error:nil];
//根據路徑建立文件(只能寫入NSData類型的數據)
[fileManager createFileAtPath:directoryPath contents:data attributes:fileDate];
//刪除文件
[fileManager removeItemAtPath:dicPath error:nil]; //刪除~/documents/dict.txt
三、NSUserDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; //單例
[defaults setValue:@"yfyfyfyfyfyfyfy" forKey:@"username"];
[defaults setValue:@"123" forKey:@"password"];
//注意:UserDefaults設置數據時,不是當即寫入,而是根據時間戳定時地把緩存中的數據寫入本地磁盤。因此調用了set方法以後數據有可能尚未寫入磁盤應用程序就終止了。出現以上問題,能夠經過調用synchornize方法強制寫入到文件中
[defaults synchronize];
//讀取
NSString *name = [defaults valueForKey:@"username"];
NSString *pwd = [defaults valueForKey:@"password"];
2、複雜對象持久化(NSKeyedArchiver)
一、複雜對象
複雜對象是在Foundation框架內不存在的數據類,沒法經過writeToFile寫入到文件內,且至少包含一個實例對象。
因爲複雜對象沒法經過writeToFile:方法寫入文件,只能將複雜對象轉化爲NSData對象,再進行數據持久化。
二、NSCoding協議
@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER
@end
三、複雜對象寫入文件
Person.h
//複雜對象歸檔 一:遵照NSCoding協議
@interface Person : NSObject<NSCoding>
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *gender;
@end
Person.m
#import "Person.h"
@implementation Person //實現NSCoding協議
#pragma mark -- 進行編碼 --
- (void)encodeWithCoder:(NSCoder *)coder
{
// [super encodeWithCode:coder]; 若是父類也遵照了NSCoding協議,確保繼承的實例變量也能被編碼,即也能被歸檔
[coder encodeObject:self.name forKey:@"name"];
[coder encodeInteger:self.age forKey:@"age"];
[coder encodeObject:self.gender forKey:@"gender"];
}
#pragma mark -- 進行解碼 --
- (id)initWithCoder:(NSCoder *)aDecoder
{
// self = [super initWithCoder:aDecoder]; 確保繼承的實例變量也能被解碼,即也能被恢復
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.gender = [aDecoder decodeObjectForKey:@"gender"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
@end
ViewController.m
類方法進行編碼\解碼(只能歸檔一個對象):
NSString *objPath = [cachesPath stringByAppendingPathComponent:@"person.txt"];
[NSKeyedArchiver archiveRootObject:person toFile:objPath];
Person *p2 = [NSKeyedUnarchiver unarchiveObjectWithFile:objPath];
實例方法(能夠歸檔多個對象):
#pragma mark -- 對複雜對象進行持久化(歸檔\編碼) --
//過程:(複雜對象->歸檔->NSData->writeToFile:)
Person *person = [[Person alloc] init];
person.name = @"yf";
person.age = 20;
person.gender = @"man";
NSMutableData *mtData = [NSMutableData data];
//建立歸檔器
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mtData];
//進行歸檔
[archiver encodeObject:person forKey:@"person"];
//***結束歸檔
[archiver finishEncoding];
//將歸檔以後的mtData寫入文件
NSString *personPath = [cachesPath stringByAppendingPathComponent:@"person.txt"];
[mtData writeToFile:personPath atomically:YES];
NSLog(@"%@", personPath);
NSLog(@"%@", mtData);
#pragma mark -- 從文件中讀取複雜對象(反歸檔\恢復\解碼) --
//過程:(讀取文件(NSData)->反歸檔->複雜對象)
//讀取
NSData *readData = [NSData dataWithContentsOfFile:personPath];
//建立反歸檔工具
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:readData];
//使用反歸檔工具對readData進行反歸檔
Person *readPerson = [unArchiver decodeObjectForKey:@"person"];
四、使用NSKeyedArchive進行深複製
好比對一個Person對象進行深複製
// 臨時存儲person1的數據
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
// 解析data,生成一個新的Person對象
Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// 分別打印內存地址
NSLog(@"person1:0x%x", person1); // person1:0x7177a60
NSLog(@"person2:0x%x", person2); // person2:0x7177cf0
3、SQLite
一、經常使用SQL語句
一、說明:建立數據庫
CREATE DATABASE database-name
二、說明:刪除數據庫
drop database dbname
三、說明:備份sql server
--- 建立 備份數據的 device
USE master
EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
--- 開始 備份
BACKUP DATABASE pubs TO testBack
四、說明:建立新表
create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
根據已有的表建立新表:
A:create table tab_new like tab_old (使用舊錶建立新表)
B:create table tab_new as select col1,col2… from tab_old definition only
五、說明:刪除新表
drop table tabname
六、說明:增長一個列
Alter table tabname add column col type
注:列增長後將不能刪除。DB2中列加上後數據類型也不能改變,惟一能改變的是增長varchar類型的長度。
七、說明:添加主鍵: Alter table tabname add primary key(col)
說明:刪除主鍵: Alter table tabname drop primary key(col)
十、說明:幾個簡單的基本的sql語句
選擇:select * from table1 where 範圍
插入:insert into table1(field1,field2) values(value1,value2)
刪除:delete from table1 where 範圍
更新:update table1 set field1=value1 where 範圍
查找:select * from table1 where field1 like ’%value1%’ ---like的語法很精妙,查資料!
排序:select * from table1 order by field1,field2 [desc]
總數:select count as totalcount from table1
求和:select sum(field1) as sumvalue from table1
平均:select avg(field1) as avgvalue from table1
最大:select max(field1) as maxvalue from table1
最小:select min(field1) as minvalue from table1
以上內容摘自:
http://www.php100.com/html/webkaifa/database/Mysql/2012/0720/10713.html
二、iOS使用SQLite
iOS操做SQLite須要用到動態庫libsqlite3.0.dylib。在Build Phases->Link Binary With Libraries下,點擊'+' ,輸入sqlite以後添加libsqlite3.0.dylib。
以後,在單例類DatabaseHandle中導入sqlite3.h便可
2.一、鏈接數據庫(若不存在則建立)
1> 獲取數據庫路徑
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *dbPath = [documentPath stringByAppendingPathComponent:@"student.db"];
2> 鏈接數據庫
int result = sqlite3_open(dbPath.UTF8String, &_db);
_db爲實例變量:
{ sqlite3 * _db; }
2.二、關閉數據庫鏈接
int result = sqlite3_close( _db);
2.三、建立表
1> SQL語句-建立表
//create table 表名(字段1 類型, 字段2 類型, ..., 字段n 類型)
NSString *createTable = @"CREATE TABLE students (\
name TEXT,\
number TEXT PRIMARY KEY,\
age INTEGER, stu BLOB)";
2> 執行SQL語句
char *errorMsg = NULL;
int result = sqlite3_exec(_db, createTable.UTF8String, NULL, NULL, &errorMsg);
if (result == SQLITE_OK) {
NSLog(@"建立表成功");
}
2.四、插入、修改、刪除數據
0> 打開數據庫
1> 新建SQL語句
NSString *insertSQL = @"insert into students(name, age, number, stu) values(?,?,?,?)";
2> 檢查語法
sqlite3_stmt *stmt = nil; //跟隨指針. 用來讓sqlite3_step()執行編譯完成的sql語句.在sqlite3中並無定義該類型指針, 是一個抽象類型(結構體指針)
int result = sqlite3_prepare_v2(_db, insertSQL.UTF8String, -1, &stmt, NULL);
語法正確時:result == SQLITE_OK
3> 字段綁定值
sqlite3_bind_?();
4> 執行編譯好的sql語句.
sqlite3_step(stmt);
5> 銷燬以前sqlite3_prepare_v2()所檢查經過的SQL語句(結束跟隨指針)
sqlite3_finalize(stmt);
6> 關閉數據庫鏈接
2.五、查詢
0> 打開數據庫
1> 新建SQL語句
NSString *selectSQL = @"select * from students";
2> 檢查語法
sqlite3_stmt *stmt = nil; //跟隨指針
int result = sqlite3_prepare(_db, selectSQL.UTF8String, -1, &stmt, NULL);
3> 取字段下的值
首先,須要用stmt指針遍歷:
while (sqlite3_step(stmt)==SQLITE_ROW)
其次,取值:
sqlite3_column_text(sqlite3_stmt *, int iCol);
iCol表明第幾列,從0開始
NSString *name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 0)];
當取出的數據爲對象時,須要解碼
NSData *data = [NSData dataWithBytes:sqlite3_column_blob(stmt, 3) length:sqlite3_column_bytes(stmt, 3)];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Student *stu = [unarchiver decodeObjectForKey:[NSString stringWithFormat:@"student%@",number]];
[unarchiver finishDecoding];
4> 銷燬跟隨指針
sqlite3_finalize(stmt);
5> 關閉數據庫鏈接
三、Demo
Student.h
@interface Student : NSObject<NSCoding>
@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, retain) NSString *number;
#pragma mark -- 自定義初始化方法 --
- (instancetype)initWithName:(NSString *)name number:(NSString *)number age:(int)age;
@end
Student.m
@implementation Student
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.number forKey:@"number"];
[aCoder encodeInt:self.age forKey:@"age"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.number = [aDecoder decodeObjectForKey:@"number"];
self.age = [aDecoder decodeIntForKey:@"age"];
}
return self;
}
- (instancetype)initWithName:(NSString *)name number:(NSString *)number age:(int)age
{
self = [super init];
if (self) {
self.name = name;
self.number = number;
self.age = age;
}
return self;
}
@end
DataBaseHandle.h
@class Student;
@interface DataBaseHandle : NSObject
#pragma mark -- 獲取單例對象 --
+ (instancetype)sharedInstance;
- (void)createDB;
#pragma mark -- 插入信息 --
- (void)insertStudent:(Student *)student;
#pragma mark -- 根據學號修改 --
- (void)updateNameOfStudent:(NSString *)name byNumber:(NSString *)number;
#pragma mark -- 根據學號刪除 --
- (void)deleteStudentByNumber:(NSString *)number;
#pragma mark -- 查詢全部學生信息 --
- (NSArray *)selectAllStudents;
@end
DataBaseHandle.m
#import "DataBaseHandle.h"
#import <sqlite3.h>
#import "Student.h"
@interface DataBaseHandle ()
{
//表示的是數據庫鏈接對象,對數據庫中表的操做都基於這個鏈接.
sqlite3 * _db;
}
@end
@implementation DataBaseHandle
static DataBaseHandle *handle = nil;
+ (instancetype)sharedInstance
{
@synchronized (self) {
if (!handle) {
handle = [[DataBaseHandle alloc] init];
}
return handle;
}
}
#pragma mark -- 鏈接數據庫 --
- (void)createDB
{
//指定存放在沙盒中的數據庫路徑
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *dbPath = [documentPath stringByAppendingPathComponent:@"student.db"];
NSLog(@"%@", dbPath);
//打開一個Sqlite數據庫(若數據庫已存在則建立)而且返回其數據庫鏈接對象
int result = sqlite3_open(dbPath.UTF8String, &_db);
if (result == SQLITE_OK) {
NSLog(@"打開數據庫成功!%d", result);
//建立表
[self createTable];
} else {
NSLog(@"打開數據庫失敗!%d", result);
}
}
#pragma mark -- 建立表 --
- (void)createTable
{
//1.SQL語句-建立表
//create table 表名(字段1 類型, 字段2 類型, ..., 字段n 類型)
NSString *createTable = @"CREATE TABLE students (\
name TEXT,\
number TEXT PRIMARY KEY,\
age INTEGER, stu BLOB)";
//2.執行sql語句
char *errorMsg = NULL;
int result = sqlite3_exec(_db, createTable.UTF8String, NULL, NULL, &errorMsg);
if (result == SQLITE_OK) {
NSLog(@"建立表成功");
} else {
NSLog(@"建立表失敗%s", errorMsg);
}
}
#pragma mark -- 關閉數據庫鏈接 --
- (void)closeDB
{
int result = sqlite3_close(_db);
if (result == SQLITE_OK) {
NSLog(@"關閉鏈接成功");
} else {
NSLog(@"關閉鏈接失敗!%d", result);
}
}
- (void)insertStudent:(Student *)student
{
[self createDB];
//1.SQL語句-插入數據
//insert into 表名(字段1, 字段2, ..., 字段n) values(value1, value2, ..., valuen)
NSString *insertSQL = @"insert into students(name, age, number, stu) values(?,?,?,?)";
sqlite3_stmt *stmt = nil; //跟隨指針. 用來讓sqlite3_step()執行編譯完成的sql語句. 在sqlite3中並無定義該類型指針, 是一個抽象類型(結構體指針)
//2.檢查語法
int result = sqlite3_prepare_v2(_db, insertSQL.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//3.字段綁定值
//第二個參數從1開始,對應insertSQL中第i個?;第三個參數表示綁定值大小,未知寫-1
sqlite3_bind_text(stmt, 1, [student.name UTF8String], -1, NULL);
sqlite3_bind_int(stmt, 2, student.age);
sqlite3_bind_text(stmt, 3, student.number.UTF8String, -1, NULL);
//student實例須要編碼後存儲(轉換爲NSData)
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:student forKey:[NSString stringWithFormat:@"student%@", student.number]];
[archiver finishEncoding];
sqlite3_bind_blob(stmt, 4, [data bytes], (int)[data length], NULL);
//4.執行編譯好的sql語句. 若是執行insert, update, delete, 只需執行一次.
sqlite3_step(stmt);
} else {
NSLog(@"INSERT ERROR %d", result);
}
//5.銷燬以前sqlite3_prepare_v2()所檢查經過的SQL語句(結束跟隨指針)
sqlite3_finalize(stmt);
[self closeDB];
}
#pragma mark -- 修改信息 --
- (void)updateNameOfStudent:(NSString *)name byNumber:(NSString *)number
{
[self createDB];
//1.SQL語句-update
//update 表名 set 字段=? where 字段=?
NSString *updateSQL = @"update students set name= ? where number= ?";
//2.檢查SQL語句是否合法
sqlite3_stmt *stmt = nil; //跟隨指針
int result = sqlite3_prepare(_db, updateSQL.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//3.綁定
sqlite3_bind_text(stmt, 1, name.UTF8String, -1, NULL);
sqlite3_bind_text(stmt, 2, number.UTF8String, -1, NULL);
//4.執行
sqlite3_step(stmt);
} else {
NSLog(@"UPDATE ERROR!%d", result);
}
//5.銷燬
sqlite3_finalize(stmt);
[self closeDB];
}
#pragma mark -- 根據學號刪除 --
- (void)deleteStudentByNumber:(NSString *)number
{
[self createDB];
//1.SQL語句-刪除
//delete from 表名 where 字段=?
NSString *deleteSQL = @"delete from students where number=?";
//2.檢查
sqlite3_stmt *stmt = nil; //跟隨指針
int result = sqlite3_prepare(_db, deleteSQL.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//3.綁定
sqlite3_bind_text(stmt, 1, number.UTF8String, -1, NULL);
//4.執行
sqlite3_step(stmt);
} else {
NSLog(@"DELETE ERROR! %d", result);
}
//結束跟隨指針
sqlite3_finalize(stmt);
[self closeDB];
}
#pragma mark -- 查詢全部學生信息 --
- (NSArray *)selectAllStudents
{
[self createDB];
//1.SQL語句-查詢
//select 字段 from 表名 where 字段=?, 字段=?
NSString *selectSQL = @"select * from students";
//2.檢查
sqlite3_stmt *stmt = nil; //跟隨指針
int result = sqlite3_prepare(_db, selectSQL.UTF8String, -1, &stmt, NULL);
NSMutableArray *stuArray = [NSMutableArray array];
if (result == SQLITE_OK) {
while (sqlite3_step(stmt)==SQLITE_ROW) {
//取字段下的值\
sqlite3_column_text(sqlite3_stmt *, int iCol);\
iCol表明第幾列,從0開始
NSString *name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 0)];
NSString *number = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 1)];
int age = sqlite3_column_int(stmt, 2);
//反歸檔(解碼)
NSData *data = [NSData dataWithBytes:sqlite3_column_blob(stmt, 3)
length:sqlite3_column_bytes(stmt, 3)];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Student *stu = [unarchiver decodeObjectForKey:[NSString stringWithFormat:@"student%@",number]];
[unarchiver finishDecoding];
NSLog(@"%@ %@ %@ %d", stu.name, stu.number, stu, stu.age);
[stuArray addObject:stu];
}
}
sqlite3_finalize(stmt);
[self closeDB];
return stuArray;
}
@end
使用:
{
...
Student *stu1 = [[Studentalloc] initWithName:@"YF"number:@"0000"age:23];
Student *stu2 = [[Student alloc] initWithName:@"ss" number:@"0001" age:24];
[DBHANDLE insertStudent:stu1];
[DBHANDLE insertStudent:stu2];
stu1.name = @"yyask";
[DBHANDLE updateNameOfStudent:stu1.name byNumber:stu1.number];
// [DBHANDLE deleteStudentByNumber:stu1.number];
[DBHANDLE selectAllStudents];
...
}