研究了几天的数据库,终于把它给搞出来了。sqlite是ios上最常用的数据库之一,大家还是有必要了解一下的。这是仿照网上的一个例子做的,有些部分写的不好,我稍作了修改,以讲解为主,主要让大家能够明白如何修改,明白原理,达到举一反三的目的。
先来看看效果图
先来看看数据库方法类,将各个 *** 作都封装在一个类里面,达到代码重用的目的,这是程序员都应该努力去实现的目标,这样在下一次用到同样的方法和类的时候,就可以直接使用封装好的类,可以节约大量的时间。
先来看看.h文件
@H_301_11@#import <Foundation/Foundation.h>#import <sqlite3.h>#define kfilename @"testdb.db"@class sqlTestList;@interface sqlService : NSObject { sqlite3 *_database;}@property (nonatomic) sqlite3 *_database;-(BOol) createTestList:(sqlite3 *)db;//创建数据库-(BOol) insertTestList:(sqlTestList *)insertList;插入数据 -(BOol) updateTestList:(sqlTestList *)updateList;更新数据-(NSMutableArray*)getTestList;获取全部数据- (BOol) deleteTestList:(sqlTestList *)deletList;删除数据:- (NSMutableArray*)searchTestList:(Nsstring*)searchString;查询数据库,searchID为要查询数据的ID,返回数据为查询到的数据@end@interface sqlTestList : NSObject重新定义了一个类,专门用于存储数据{ int sqlID; Nsstring *sqlText; Nsstring *sqlname;}@property (nonatomic) sqlID;@property (nonatomic,retain) Nsstring *sqlText;@property (nonatomic,0)">sqlname;@end@H_301_11@
再来看看.m文件
// sqlService.m sqlite3Test Created by fengxiao on 11-11-28. copyright 2011 __MyCompanyname__. All rights reserved.//#import "sqlService.h"@implementation sqlService@synthesize _database;- (ID)init{ return self;}- (voID)dealloc{ [super dealloc];}获取document目录并返回数据库目录- (Nsstring *)datafilePath{ NSArray *paths = NSSearchPathForDirectorIEsInDomains(NSdocumentDirectory,NSUserDomainMask,YES); Nsstring *documentsDirectory = [paths objectAtIndex:0]; NSLog(@"=======%@",documentsDirectory); return [documentsDirectory stringByAppendingPathComponent:data.db"];这里很神奇,可以定义成任何类型的文件,也可以不定义成.db文件,任何格式都行,定义成.sb文件都行,达到了很好的数据隐秘性 }创建,打开数据库- (BOol)openDB { 获取数据库路径 Nsstring *path = [self datafilePath]; 文件管理器 NSfileManager *fileManager = [NSfileManager defaultManager]; 判断数据库是否存在 BOol find = [fileManager fileExistsAtPath:path]; 如果数据库存在,则用sqlite3_open直接打开(不要担心,如果数据库不存在sqlite3_open会自动创建) if (find) { NSLog(Database file have already existed.); 打开数据库,这里的[path UTF8String]是将Nsstring转换为C字符串,因为sqlite3是采用可移植的C(而不是 Objective-C)编写的,它不知道什么是Nsstring. if(sqlite3_open([path UTF8String],&_database) != sqlITE_OK) { 如果打开数据库失败则关闭数据库 sqlite3_close(self._database); NSLog(Error: open database file.); NO; } 创建一个新表 [self createTestList:self._database]; YES; } 如果发现数据库不存在则利用sqlite3_open创建数据库(上面已经提到过),与上面相同,路径要转换为C字符串 sqlITE_OK) { [self createTestList:self._database]; YES; } else { 如果创建并打开数据库失败则关闭数据库 sqlite3_close(self._database); NSLog(); NO; } NO;}创建表- (BOol) createTestList:(sqlite3*)db { 这句是大家熟悉的SQL语句 char *sql = create table if not exists testtable(ID INTEGER PRIMARY KEY autoINCREMENT,testID int,testValue text,testname text)"; testID是列名,int 是数据类型,testValue是列名,text是数据类型,是字符串类型 sqlite3_stmt *statement; sqlite3_prepare_v2 接口把一条SQL语句解析到statement结构里去. 使用该接口访问数据库是当前比较好的的一种方法 NSInteger sqlReturn = sqlite3_prepare_v2(_database,sql,-1,&statement,nil); 第一个参数跟前面一样,是个sqlite3 * 类型变量, 第二个参数是一个 sql 语句。 第三个参数我写的是-1,这个参数含义是前面 sql 语句的长度。如果小于0,sqlite会自动计算它的长度(把SQL语句当成以第四个参数是sqlite3_stmt 的指针的指针。解析以后的SQL语句就放在这个结构里。 结尾的字符串)。 第五个参数是错误信息提示,一般不用,为nil就可以了。 如果这个函数执行成功(返回值是 sqlITE_OK 且 statement 不为NulL ),那么下面就可以开始插入二进制数据。 如果SQL语句解析出错的话程序返回if sqlITE_OK) { NSLog((sqlReturn !=Error: Failed to prepare statement:create test table NO; } 执行SQL语句int sqlite3_step(statement); success =释放sqlite3_stmt sqlite3_finalize(statement); 执行SQL语句失败if sqlITE_DONE) { NSLog( ( success !=Error: Failed to dehydrate:create table test NO; } NSLog(Create table 'testtable' successed.); YES;}插入数据)insertList { -(BOol) insertTestList:(sqlTestList *先判断数据库是否打开 ([self openDB]) { sqlite3_stmt statement; *这个 sql 语句特别之处在于 values 里面有个? 号。在sqlite3_prepare函数里,?号表示一个未定的值,它的值等下才插入。static INSERT INTO testtable(testID,testValue,testname) VALUES(?,?,?) ; intif success2 = sqlite3_prepare_v2(_database,NulL); sqlITE_OK) { NSLog( (success2 !=Error: Failed to insert:testtable); sqlite3_close(_database); 这里的数字1,2,3代表上面的第几个问号,这里将三个值绑定到三个绑定变量1 sqlite3_bind_int(statement,2执行插入语句,[insertList.sqlText UTF8String],sqlITE_TRANSIENT); sqlite3_bind_text(statement,128)">3,[insertList.sqlname UTF8String],sqlITE_TRANSIENT); sqlite3_step(statement); success2 =释放statement sqlite3_finalize(statement); 如果插入失败if sqlITE_ERROR) { NSLog( (success2 ==Error: Failed to insert into the database with message.关闭数据库 sqlite3_close(_database); NO; } sqlite3_close(_database); 获取数据)getTestList{ NSMutableArray - (NSMutableArray*10*array = [NSMutableArray arrayWithCapacity:]; 判断数据库是否打开 ([self openDB]) { sqlite3_stmt nil; *statement =SQL语句SELECT testID,testname FROM testtable 从testtable这个表中获取 testID,testname,若获取全部的话可以用*代替testID,testname。if Error: Failed to prepare statement with message:get testValue. (sqlite3_prepare_v2(_database,&statement,NulL) != { //查询结果集中一条一条的遍历所有的记录,这里的数字对应的是列值,注意这里的列值,跟上面sqlite3_bind_text绑定的列值不一样!一定要分开,不然会crash,只有这一处的列号不同,注意!while sqlITE_ROW) { sqlTestList (sqlite3_step(statement) == [[sqlTestList alloc] init] ; sqlList.sqlID * sqlList =0= sqlite3_column_int(statement,); charchar* strText = (); sqlList.sqlText *)sqlite3_column_text(statement,0)">1 [Nsstring stringWithUTF8String:strText]; =char2 *strname = (); sqlList.sqlname [Nsstring stringWithUTF8String:strname]; [array addobject:sqlList]; [sqlList release]; } } sqlite3_finalize(statement); sqlite3_close(_database); } =return定义了自动释放的NSArray,这样不是个好办法,会造成内存泄露,建议大家定义局部的数组,再赋给属性变量。 [array retain];}更新数据)updateList{ -(BOol) updateTestList:(sqlTestList * ([self openDB]) { sqlite3_stmt 这相当一个容器,放转化OK的SQL语句 *statement;组织SQL语句update testtable set testValue = ? and testname = ? WHERE testID = ? 将SQL语句放入sqlite3_stmt中int Error: Failed to update:testtable success = sqlite3_prepare_v2(_database,255)">if (success !=这里的数字1,2,3代表第几个问号。这里只有1个问号,这是一个相对比较简单的数据库 *** 作,真正的项目中会远远比这个复杂 绑定text类型的数据库数据执行SQL语句。这里是更新数据库 sqlite3_bind_text(statement,[updateList.sqlname UTF8String],[updateList.sqlText UTF8String],sqlITE_TRANSIENT); sqlite3_bind_int(statement,updateList.sqlID); 如果执行失败 success =if Error: Failed to update the database with message. (success ==执行成功后依然要关闭数据库 NO;}删除数据)deletList{ - (BOol) deleteTestList:(sqlTestList *statement; delete from testtable where testID = ? and testValue = ? and testname = ?; Error: Failed to delete:testtable这里的数字1,2,3代表第几个问号。这里只有1个问号,这是一个相对比较简单的数据库 *** 作,真正的项目中会远远比这个复杂Error: Failed to delete the database with message. sqlite3_bind_int(statement,deletList.sqlID); sqlite3_bind_text(statement,[deletList.sqlText UTF8String],[deletList.sqlname UTF8String],sqlITE_TRANSIENT); NO; }查询数据)searchString{ NSMutableArray - (NSMutableArray*)searchTestList:(Nsstring*SQL语句*array = [NSMutableArray arrayWithCapacity:SELECT * from testtable where testname like \ Nsstring *querysql = [Nsstring stringWithFormat:"""%@\constchar [querysql UTF8String]; *sql = char *sql = "SELECT * FROM testtable WHERE testname like ?";这里用like代替=可以执行模糊查找,原来是"SELECT * FROM testtable WHERE testname = ?"Error: Failed to prepare statement with message:search testValue. NO; } { sqlTestList [[sqlTestList alloc]init];*searchList = sqlite3_bind_int(statement,1,searchID);查询结果集中一条一条的遍历所有的记录,这里的数字对应的是列值。 sqlite3_bind_text(statement,[searchString UTF8String],sqlITE_TRANSIENT); [[sqlTestList alloc] init] ; sqlList.sqlID 3= sqlite3_column_int(statement,128)">2 [Nsstring stringWithUTF8String:strname]; [array addobject:sqlList]; [sqlList release]; } [searchList release]; } sqlite3_finalize(statement); sqlite3_close(_database); } [array retain];}@end@implementation刚才.h文件里定义的类在这实现 sqlTestList sqlID; sqlText; sqlname;) init{ sqlID -(; sqlText = @""= ; sqlname ; = self;};) dealloc{ -(if nil)) { [sqlText release]; [sqlname release]; } [super dealloc];} ((sqlText != nil) && (sqlname !=" 这就是封装好的类,可以重用哦!下面是添加数据页面
这也是一个类,来看.h文件
#import <UIKit/UIKit.h> operatesqlVIEwController : UIVIEwController { UITextFIEld IDValue; UITextFIEld *textValue; UITextFIEld *textname; *int区分数据插入与更新 oprateType;sqlValue;}@property (nonatomic,retain) IBOutlet UITextFIEld sqlTestList *sqlValue;@property (nonatomic) *IDValue;@property (nonatomic,0)">textValue;@property (nonatomic,0)">textname;@property (nonatomic,retain) sqlTestList * oprateType;operatesqlVIEwController.h operatesqlVIEwController IDValue; textValue; oprateType; sqlValue; textname;)dIDReceiveMemoryWarning { - ( Releases the vIEw if it doesn't have a supervIEw. [super dIDReceiveMemoryWarning]; Release any cached data,images,etc. that aren't in use.})vIEwDIDLoad{ UIbarbuttonItem - ( [[UIbarbuttonItem alloc] initWithTitle:*backbutton =返回 style:UIbarbuttonItemStylebordered target:self action:@selector(dismiss:)]; UIbarbuttonItem 保存*savebutton = style:UIbarbuttonItemStylebordered target:self action:@selector(saveValue:)]; [[self navigationItem] setleftbarbuttonItem:backbutton]; [[self navigationItem] setRightbarbuttonItem:savebutton]; [backbutton release]; [savebutton release]; if) { [self.navigationItem setTitle: (oprateType == 数据插入]; } elseif ){ [self.navigationItem setTitle:(oprateType == 数据更新]; IDValue.text %d= [Nsstring stringWithFormat: sqlValue.sqlText; textname.text sqlValue.sqlname; }}=)vIEwDIDUnload { IDValue - ( nil; textValue = nil; textname = nil; sqlValue = nil; [super vIEwDIDUnload]; = Release any retained subvIEws of the main vIEw. e.g. self.myOutlet = nil;})dealloc { [IDValue release]; [textValue release]; [sqlValue release]; [textname release]; [super dealloc];}- (voID- ()sender{ [[self parentVIEwController] dismissModalVIEwControllerAnimated:YES];})dismiss:(voID- ()sender{ )saveValue:(if) { UIAlertVIEw (IDValue.text.length == 提示*alert = [[UIAlertVIEw alloc] initWithTitle: message:请输入ID"delegate :self cancelbuttonTitle:好 otherbuttonTitles:nil]; [alert show]; [alert release]; ; } if) { UIAlertVIEw (textValue.text.length == message:*alert = [[UIAlertVIEw alloc] initWithTitle:请输入电话":self cancelbuttonTitle: otherbuttonTitles:nil]; [alert show]; [alert release]; if请输入姓名 (textname.text.length == ; } 初始化数据库 [[sqlService alloc] init]; sqlService *sqlSer =数据库插入) { sqlTestList [[sqlTestList alloc]init]; sqlInsert.sqlID *sqlInsert = [IDValue.text intValue]; sqlInsert.sqlText = textValue.text; sqlInsert.sqlname = textname.text; =调用封装好的数据库插入函数 ([sqlSer insertTestList:sqlInsert]) { UIAlertVIEw 插入数据成功*alert = [[UIAlertVIEw alloc] initWithTitle: otherbuttonTitles:nil]; [alert show]; [alert release]; } { UIAlertVIEw 插入数据失败*alert = [[UIAlertVIEw alloc] initWithTitle: otherbuttonTitles:nil]; [alert show]; [alert release]; } [sqlInsert release]; } 数据库更新){ sqlTestList [[sqlTestList alloc]init]; newValue.sqlID *newValue = [IDValue.text intValue]; newValue.sqlText = textValue.text; newValue.sqlname =调用封装好的更新数据库函数= ([sqlSer updateTestList:newValue]) { UIAlertVIEw 更新数据成功*alert = [[UIAlertVIEw alloc] initWithTitle:更新数据失败 otherbuttonTitles:nil]; [alert show]; [alert release]; } [newValue release]; }}@interface 代码写的有些啰嗦,不过不难容易看懂,不多解释了,要在xib文件中添加3个UITextFIEld和ulabel,要记得连线。在主界面的.h文件
" { UItableVIEw sqlite3TestVIEwController : UIVIEwController<UItableVIEwDelegate,UItableVIEwDataSource>utableVIEw; NSArray *ListData; UISearchbar *searchbar;//搜索栏 }@property (nonatomic,retain) IBOutlet UItableVIEw *utableVIEw;@property (nonatomic,retain) IBOutlet UISearchbar *searchbar;@property (nonatomic,retain) NSArray *ListData;* (IBAction)insertValue;- (IBAction)updateValue;- (IBAction)getAllValue;- (IBAction)deleteValue;- (IBAction)searchValue;- .m文件 sqlite3TestVIEwController.msqlite3TestVIEwController.h sqlite3TestVIEwController utableVIEw; ListData; searchbar;)vIEwDIDLoad{ sqlService - ( [[sqlService alloc] init]; ListData *sqlSer =先初始化那个专门用于存数据的类,才调用类获取数据的方法= [sqlSer getTestList];voID在这里写是为了等待时间缩短一点,数据如果很多的,在这里写可以让数据提前加载)vIEwDIDAppear:(BOol)animated{ [[sqlService alloc] init]; ListData sqlService *sqlSer = [sqlSer getTestList]; [sqlSer release]; [utableVIEw reloadData];}=)vIEwDIDUnload { utableVIEw - ( nil; ListData = nil; searchbar =)dealloc { [utableVIEw release]; [ListData release]; [searchbar release]; [super dealloc];}= (IBAction)insertValue{ [searchbar resignFirstResponder];-触发这个insertValue方法时隐藏键盘 [[operatesqlVIEwController alloc] init ]; UINavigationController operatesqlVIEwController *operateController = [[UINavigationController alloc] initWithRootVIEwController:operateController];*theNavController =这里如果不初始化一个UINavigationController类的对象来存放operatesqlVIEwController类的UIVIEwController,就不会有最上面的导航栏了。0 operateController.oprateType = optrateType为0时为数据插入; [operateController release]; theNavController.navigationbar.tintcolor [UIcolor blackcolor]; [self presentModalVIEwController:theNavController animated:YES]; [theNavController release];}= (IBAction)updateValue{ [searchbar resignFirstResponder]; NSIndexPath - [utableVIEw indexPathForSelectedRow]; *indexPath =if nil) { UIAlertVIEw (indexPath ==请选择要更新的项*alert = [[UIAlertVIEw alloc] initWithTitle:; } NSUInteger row [indexPath row]; sqlTestList = [[sqlTestList alloc]init]; sqlList *sqlList =1= [ListData objectAtIndex:(row - 在这里面获取点击的行,因为table的第一行没显示数据,所以这里要减1。)]; operatesqlVIEwController [[UINavigationController alloc] initWithRootVIEwController:operateController]; operateController.oprateType *operateController =1= optrateType为1时为数据更新; sqlList; theNavController.navigationbar.tintcolor operateController.sqlValue = [UIcolor blackcolor]; [self presentModalVIEwController:theNavController animated:YES]; [sqlList release]; [operateController release]; [theNavController release];}= (IBAction)getAllValue{ [searchbar resignFirstResponder]; sqlService - [sqlSer getTestList]; [utableVIEw reloadData]; [sqlSer release]; }*sqlSer = (IBAction)deleteValue{ [searchbar resignFirstResponder]; NSIndexPath - [utableVIEw indexPathForSelectedRow]; *indexPath =请选择要删除的项)]; sqlService [[sqlService alloc] init]; *sqlSer = ([sqlSer deleteTestList:sqlList]) { UIAlertVIEw message:*alert = [[UIAlertVIEw alloc] initWithTitle:删除数据成功":self cancelbuttonTitle: otherbuttonTitles:nil]; [alert show]; [alert release]; 删除成功后重新获取数据更新列表 [sqlSer getTestList]; [utableVIEw reloadData]; } ListData = { UIAlertVIEw 删除数据失败*alert = [[UIAlertVIEw alloc] initWithTitle:; } [sqlList release]; [sqlSer release];} (IBAction)searchValue{ -if]) { UIAlertVIEw ([searchbar.text isEqualToString:请输入要查询数据的ID*alert = [[UIAlertVIEw alloc] initWithTitle: { int IDNum = [searchbar.text intValue]; searchbar.text; sqlService Nsstring *str = [[sqlService alloc] init]; ListData *sqlSer = [sqlSer searchTestList:str]; =ifsorry,未查询到数据,请查看name是否有误 ([ListData count] == otherbuttonTitles:nil]; [alert show]; [alert release]; ; } [searchbar resignFirstResponder]; [utableVIEw reloadData]; [sqlSer release]; }}#pragma#pragma mark -)tableVIEw numberOfRowsInSection:(NSInteger)section{ mark table VIEw Data Source Methods- (NSInteger)tableVIEw:(UItableVIEw * Return the number of rows in the section.return 从第二行开始,第一行不显示数据 [ListData count] + })indexPath{ Nsstring - (UItableVIEwCell *)tableVIEw:(UItableVIEw *)tableVIEw cellForRowAtIndexPath:(NSIndexPath *cell%d*CustomIDentifIEr = [Nsstring stringWithFormat:cell不重用 [tableVIEw dequeueReusableCellWithIDentifIEr:CustomIDentifIEr]; UItableVIEwCell *cell =if) cell.selectionStyle (indexPath.row == UItableVIEwCellSelectionStyleNone; =if nil ) { cell ( cell == [[[UItableVIEwCell alloc] initWithStyle:UItableVIEwCellStyleValue1 reuseIDentifIEr:CustomIDentifIEr] autorelease]; cell.backgroundcolor = [UIcolor clearcolor]; } =if) { NSUInteger row (indexPath.row > [indexPath row]; sqlTestList = [[sqlTestList alloc] init] ; *sqlList =if nil) sqlList (ListData !=读取数据的时候也要减一行,从第二行开始= [ListData objectAtIndex: (row - UILabel 0*nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(40+)]; UILabel ,128)">10,128)">70,128)">3090*IDLabel = [[UILabel alloc]initWithFrame:CGRectMake()]; UILabel +180*valueLabel = [[UILabel alloc]initWithFrame:CGRectMake()]; nameLabel.text + sqlList.sqlname; IDLabel.text = sqlList.sqlText; valueLabel.text = { = [Nsstring stringWithFormat:forint (0 i = 3; i < ) { UILabel ; i ++90*label = [[UILabel alloc]initWithFrame:CGRectMake()]; NSArray * i + 姓名*array = [NSArray arrayWithObjects:"电话,0)">ID [array objectAtIndex:i]; label.backgroundcolor [UIcolor clearcolor]; [cell.contentVIEw addSubvIEw:label]; [label release]; } } = cell;})indexPath{ [searchbar resignFirstResponder]; - (NSIndexPath*)tableVIEw:(UItableVIEw *)tableVIEw willSelectRowAtIndexPath:(NSIndexPath *) { return让第一行不能点击 nil; } else indexPath;} @end 总结
以上是内存溢出为你收集整理的sqlite3 的增删查找全部内容,希望文章能够帮你解决sqlite3 的增删查找所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)