【iOS】sqlite3的使用(増删改查)
目录:
一、sqlite3常用函数
二、将sqlite3集成到项目,实现増删改查
三、封装DBManager
四、Demo
一、sqlite3常用函数及解释
(1)sqlite3_open:
用来创建和打开数据库文件,接收两个参数,第一个是数据库的名字,第二个是数据库的句柄。如果数据库文件不存在,将首先新建它,然后再打开它,否则只是打开它。
(2)sqlite3_prepare_v2:
使用格式化的字符串来获得sql准备语句(prepared statement),然后转化为可被SQLite3识别的执行语句。(实际上这个函数并不执行这个SQL语句)
(3)sqlite3_step:
这个函数执行上一个函数调用创建的准备语句,这个语句执行到结果的第一行可用的位置,再次调用sqlite3_setp(),会继续前进到结果的第二行。当执行插入、更新、删除操作时会被调用一次,当执行取回数据时可以执行多次。这个函数不能在sqlite3_preprare_v2之前调用。
(4)sqlite3_column_count:
返回表的列数
(5)sqlite3_column_text:
以text的格式返回列的内容(实际上是C的char*类型)。它接收两个参数,SQLite语句和列的索引。
(6)sqlite3_column_name:
返回列的名字,参数和上一个函数一样
(7)sqlite3_changes:
返回执行语句后受影响的行数
(8)sqlite3_last_insert_rowid:
返回最后插入的行的id
(9)sqlite3_errmsg:
返回SQLite错误描述
(10)sqlite3_finalize:
从内存删除之前sqlite3_prepare_v2函数创建的准备语句
(11)sqlite3_close:
关闭数据库连接,在结束任何数据库数据修改后调用,它将释放其存储的系统资源。
二、将sqlite3集成到项目,实现増删改查
#define DBNAME @"myDB.sqlite"
#define TABLENAME @"PERSONINFO"
#define NAME @"name"
@interface ViewController (){sqlite3 *db;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documents = [paths objectAtIndex:0];NSString *database_path = [documents stringByAppendingPathComponent:DBNAME]; if (sqlite3_open([database_path UTF8String], &db)!= SQLITE_OK) {sqlite3_close(db);NSLog(@"打开数据库失败");}
4. 新建一个sql语句操作数据库的函数
-(void)execSql:(NSString *)sql
{ char *err; if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) { sqlite3_close(db); NSLog(@"数据库操作数据失败!"); }
}
5.创建数据表,表名为2中的宏定义PERSONINFO
NSString *sqlCreateTable = @"CREATE TABLE IF NOT EXISTS PERSONINFO(peopleInfoID integer primary key, firstname text, lastname text, age integer);";
[self execSql:sqlCreateTable];
6.插入一条名字为张三,年龄22岁的记录
NSString *sql = [NSString stringWithFormat:@"insert into peopleInfo values(null, '%@', '%@', %d)", @“张”,@“三”,22]; [self execSql:sql];
NSString *sqlQuery = @"SELECT * FROM PERSONINFO"; sqlite3_stmt * statement; if (sqlite3_prepare_v2(db, [sqlQuery UTF8String], -1, &statement, nil) == SQLITE_OK) { while (sqlite3_step(statement) == SQLITE_ROW) { char *firstName = (char*)sqlite3_column_text(statement, 1); NSString *firstNameStr = [[NSString alloc]initWithUTF8String:firstName]; <pre name="code" class="objc"> char *lastName = (char*)sqlite3_column_text(statement, 2); NSString *lastNameStr = [[NSString alloc]initWithUTF8String:lastName];
int age = sqlite3_column_int(statement, 3); NSLog(@"firstName:%@ lastName:%@ age:%d",firstNameStr,lastNameStr, age);} } sqlite3_close(db);
三、封装DBManager
#import <Foundation/Foundation.h>@interface DBManager : NSObject@property (nonatomic, strong) NSMutableArray *arrColumnNames;//存储列名
@property (nonatomic) int affectedRows;//记录被改变的行数
@property (nonatomic) long long lastInsertedRowID;//记录最后插入行的id-(NSArray *)loadDataFromDB:(NSString *)query;//查询
-(void)executeQuery:(NSString *)query;//插入、更新、删除
-(instancetype)initWithDatabaseFilename:(NSString *)dbFilename;//初始化方法
-(BOOL)createTableWithSql:(const char *)sql_stmt;//新建表@end
(3).m文件
#import "DBManager.h"
#import <sqlite3.h> //导入sqlite3的头文件@interface DBManager()@property (nonatomic, strong) NSString *documentsDirectory;
@property (nonatomic, strong) NSString *databaseFilename;
@property (nonatomic, strong) NSMutableArray *arrResults;@end@implementation DBManager-(instancetype)initWithDatabaseFilename:(NSString *)dbFilename{self = [super init];if (self) {//获得存储路径NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);self.documentsDirectory = [paths objectAtIndex:0];//数据库名self.databaseFilename = dbFilename;}return self;
}#pragma mark 建表
-(BOOL)createTableWithSql:(const char *)sql_stmt{BOOL isSuccess = YES;//检查数据库文件是否已经存在NSString *destinationPath = [self.documentsDirectory stringByAppendingPathComponent:self.databaseFilename];NSLog(@"path:%@",destinationPath);if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {sqlite3 *database = nil;const char *dbpath = [destinationPath UTF8String];if (sqlite3_open(dbpath, &database) == SQLITE_OK){char *errMsg;if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)!= SQLITE_OK){isSuccess = NO;NSLog(@"Failed to create table");}sqlite3_close(database);}else{isSuccess = NO;NSLog(@"Failed to open/create table");}}return isSuccess;
}#pragma mark 执行sql语句
-(void)runQuery:(const char *)query isQueryExecutable:(BOOL)queryExecutable{//创建一个sqlite3对象sqlite3 *sqlite3Database;//设置数据库路径NSString *databasePath = [self.documentsDirectory stringByAppendingPathComponent:self.databaseFilename];//初始化存储结果的arrayif (self.arrResults != nil) {[self.arrResults removeAllObjects];self.arrResults = nil;}self.arrResults = [[NSMutableArray alloc] init];//初始化存储列名的arrayif (self.arrColumnNames != nil) {[self.arrColumnNames removeAllObjects];self.arrColumnNames = nil;}self.arrColumnNames = [[NSMutableArray alloc] init];//打开数据库BOOL openDatabaseResult = sqlite3_open([databasePath UTF8String], &sqlite3Database);if(openDatabaseResult == SQLITE_OK) {//声明一个sqlite3_stmt对象,存储查询结果sqlite3_stmt *compiledStatement;//将所有数据加载到内存BOOL prepareStatementResult = sqlite3_prepare_v2(sqlite3Database, query, -1, &compiledStatement, NULL);if(prepareStatementResult == SQLITE_OK) {//是否是查询语句if (!queryExecutable){//用来保存每一行数据NSMutableArray *arrDataRow;//将结果一行行地加入到arrDataRow中while(sqlite3_step(compiledStatement) == SQLITE_ROW) {//初始化arrDataRowarrDataRow = [[NSMutableArray alloc] init];//获得列数int totalColumns = sqlite3_column_count(compiledStatement);//读取和保存每一列数据for (int i=0; i<totalColumns; i++){//将数据转化为charchar *dbDataAsChars = (char *)sqlite3_column_text(compiledStatement, i);//数据不为空则加到arrDataRow中if (dbDataAsChars != NULL) {//将char转化为string.[arrDataRow addObject:[NSString stringWithUTF8String:dbDataAsChars]];}//保存列名(只保存一次)if (self.arrColumnNames.count != totalColumns) {dbDataAsChars = (char *)sqlite3_column_name(compiledStatement, i);[self.arrColumnNames addObject:[NSString stringWithUTF8String:dbDataAsChars]];}}//如果不为空,将每行的数据保存到if (arrDataRow.count > 0) {[self.arrResults addObject:arrDataRow];}}}else {//插入、更新、删除等操作if (sqlite3_step(compiledStatement) == SQLITE_DONE) {// 被改变了多少行self.affectedRows = sqlite3_changes(sqlite3Database);// 最后插入的行idself.lastInsertedRowID = sqlite3_last_insert_rowid(sqlite3Database);}else {// 插入、更新、删除等错误NSLog(@"DB Error: %s", sqlite3_errmsg(sqlite3Database));}}}else {//打开错误NSLog(@"%s", sqlite3_errmsg(sqlite3Database));}// 释放内存sqlite3_finalize(compiledStatement);}// 关闭数据库sqlite3_close(sqlite3Database);
}-(NSArray *)loadDataFromDB:(NSString *)query{// 执行查询[self runQuery:[query UTF8String] isQueryExecutable:NO];// 返回查询结果return (NSArray *)self.arrResults;
}-(void)executeQuery:(NSString *)query{// 执行插入、更新、删除等[self runQuery:[query UTF8String] isQueryExecutable:YES];
}@end
四、使用三中DBManager完成一个Demo,实现增删改查,效果如下图,源代码:http://download.csdn.net/detail/dolacmeng/8816001
相关文章:

网上搜集了点资料,学web的人互相分享共同进步吧(php编码的好习惯必须养成)...
网上搜集了点资料,学web的人互相分享共同进步吧 一、优秀的代码应该是什么样的? 优秀的PHP代码应该是结构化的。大段的代码应该被分割整理成一个个函数或方法,而那些不起眼的小段代码则应该加上注释,以便日后清楚它们的用途。而且…

div模拟textarea文本域轻松实现高度自适应——张鑫旭
by zhangxinxu from http://www.zhangxinxu.com本文地址: http://www.zhangxinxu.com/wordpress/?p1362 一、关于textarea文本域以及高度自适应 textarea标签为表单元素,一般用在多行文字的输入。在web应用上常见的是评论输入框,微博信息输入…
【iOS】Mapkit的使用:地图显示、定位、大头针、气泡等
以前做项目用高德地图SDK,需要注册账号和AppID,然后下载SDK集成到项目中,比较麻烦,这几天看了下苹果自带的MapKit框架,感觉挺好用,官方文档也介绍得很详细,所以按照官方文档写了个demoÿ…
java.lang.NoSuchMethodError: org.springframework.core.io.ResourceEditor错误
一般是jar包冲突,或者某些jar包版本不同。 如上,spring其他包的版本均为4.2.5,而spring-webmvc的jar包为1.2.6版本,造成版本冲突。 把该包版本改为4.2.5,宣告成功! 转载于:https://www.cnblogs.com/toSeeMy…

SDUTOJ 1293 乘积最大的分解(数论)
乘积最大的分解思路: 让分解出来的因子有尽可能多的3,剩下的用2补全。 最开始思路错了,WA了好长时间 ! 函数中n 1的情况应该是不用,经测试数据中没有这组。 *注意用 long long 99的时候会超int的数据范围 1 #include …
列表及字典生成式
列表生成式: 列表生成式就是一个用来生成列表的特定语法形式的表达式。 语法格式: [exp for iter_var in iter] 迭代iter中的每个元素; 每次迭代都先把结果赋值给iter_var,然后通过exp得到一个新的计算值; 最后把…

[SQL基础教程] 1-5 表的删除和更新
[SQL基础教程] 1-5 表的删除和更新 表的删除 语法DROP TABLE <表名>; 法则 1-12 删除的表无法恢复 表定义的更新 语法ALTER TABLE<表名> ADD COLUMN<列的定义>; // 添加列 ALTER TABLE<表名> DROP COLUMN<列的定义>; // 删除列 ps: **Oracle、SQ…
【iOS】自定义控件入门:可拖动的环形进度
有时候UIKit的标准控件并不能满足我们的需求,因此我们可以通过自定义控件得到满足我们需求的控件,例如这篇文章将教你如何自定义一个圆形的进度条,并且用户可以通过拖动进度条上的手柄来改变进度值。主要参考了这篇文章:HOW TO BU…

在.NET2.0中解析Json和Xml
在.NET2.0中解析Json和Xml 在.NET解析json有很多方法,这里介绍最简单也用的最多的一种。 一、添加引用 解析Json,先下载开源控件 Newtonsoft.Json.dll 下载地址:http://files.cnblogs.com/gosky/Newtonsoft.Json%E9%9B%86%E5%90%88.zip 解压以…
虚拟机的基本操作
1、用户界面 [kioskfoundation156 Desktop]$ kiosk #打开shell的用户 #分隔符 foundation156 #主机名称 Desktop #工作目录名称 $ ##身份提示符,#表示超级用户,$表示普通用户 特别注意&a…

strong assign属性
strong:这要求运行时自动地保留对这个对象的引用。换而言之,ARC(Automatic Reference Counting)在运行时会一直把这个对象保留在内存里,直到它不再被任何其他对象引用。之后,其所占的内存会被自动释放。assign:表示这…

iOS7的界面上移问题
第一种方法:修改BaseSDK XCode5的默认BaseSDK是iOS7,所以要修改成工程文件创建时的BaseSDK。但是XCode5中默认只带有iOS7的SDK,所以要想能做到更改SDK,我们就要添加旧的SDK。 1.从苹果开发者中心下载旧版本XCode,https…
【Android】ActionBar的使用(1)
前(fei)言(hua):转行iOS开发半年,很久没接触Android了,前几天去上课,听着实在无聊,随手拿了同学的一本《Android UI设计》,发现有好多基础知识自己虽然用过&a…
装饰器及例题分析
知识点: 装饰器的定义: - 装饰器的实现是函数里面嵌套函数; - 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能; - 装饰器需要传递一个函数, 返回值也是一个函数对象. 1、map函数 def …

iOS开发系列--让你的应用“动”起来
概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画、关键帧动画、动画组、转场动画,如何通…

ios app 砸壳
这里介绍使用dumpdecrypted砸壳。原理是用DYLD_INSERT_LIBRARIES这个环境变量加载脱壳的动态链接库dumpdecrypted.dylib 1.ssh连接上越狱的机器,输入密码alpine ssh root192.168.7.116 2.打开要砸的app,ps aux | grep var找到它的目录 yigewangde-iPhone…

基于visual Studio2013解决面试题之0804复杂链表
题目解决代码及点评/*复杂链表的拷贝,现在有一个复杂链表,完成一个clone函数拷贝一个链表复杂链表是指struct Node{struct Node* _next;struct Node* _sibling; // sibling指向链表中任意一个节点,或者…
python考试编程题
3. a: while True: s raw_input(变量名为:) if s exit: print 退出 break #判断是否由字母或下划线组成 if s[0].isalpha() or s[0] _: for i in s[1:]: if not (i.isalnum() or i _): print %s变量…

【分享】bootstrap学习笔记
一、基础知识 1.整体架构以响应式设计为理念,css组件、js插件jquery、基础布局组件和12栅格系统搭建。1.1响应式设计:结合media query查询,适应更多设备,自动适应用户的设备环境,不必为每个终端做一个特定的版本。2.cs…

大三下学期总结
本学期的最后一门考试已经考完了,就相当于本学期要结束了,本学期结束了,就相当于大学的学习生活接近尾声了。感觉大三下开学也只在不久之前,但是真的要结束了,我觉得这学期实在是过得太充实了,一直是在追着…

通过 cygwin64 自己编译对应的 Tera Term cyglaunch.exe
步骤如下: 将 cygterm.tar.gz解压到任意目录,当然要cygwin容易操作。(本例直接放到$HOME目录下,启动cygwin后的默认目录,如果之前没有更改的话)将 Makefile 中的 -mno-cygwin 选项删除。执行make࿰…
面向对象概念及三大特点
面向对象: 面向对象的基本概念 面向对象 oop : object oriented programming 我们之前学习的编程方式就是面向过程的 面向过程和面向对象,是两种不同的编程方式 对比面向过程的特点,可以更好的了解什么是面向对象 过程和函数(都是对一段…
【Android】ViewPager实现无限循环滚动
最近做的一个项目,客户要求在ViewPager实现的主页面中滑动到最后一页后继续滑动能返回到第一页,也就是实现无限循环滚动,效果如下: 看了下ViewPager没有滑到尽头的回调方法,因此想到的解决方案是,在原来的最…

LabVIEW 三维机器人展示
本程序是使用solidworks绘制模型图,通过LabVIEW 2013导入wrl文件完成. 程序效果如下: (工程文件) (3维机器人模型) (控制界面,未做美化....因为实际上这部分程序只是一小部分,主程序运行时,这部分面板是不显示的~\(≧▽≦)/~啦啦啦) 程序下载: 百度网盘: http://pan.baidu.com/…

SqlServer2008查询性能优化_第一章
转载于:https://www.cnblogs.com/MiaoXin/p/5813207.html
Python之类
1、类的结构 1.使用面向对象开发,第一步是设计类 2.使用 类名() 创建对象,创建对象的动作有两步 1.在内存中为对象分配空间 2.调用初始化方法__init___ 为对象初始化 3.对象创建后,内存中就有了一个对象的实实在在的存在--实例 因此…

祝大家圣诞节快乐!
在圣诞节来临之际,分享这份网页的代码,祝愿大家圣诞节快乐!点击这里查看效果 以下是源代码,可以保存到html文件打开看效果: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht…
【iOS官方文档翻译】UICollectionView与UICollectionViewFlowLayout
(一)先来简单回顾一下UICollectionView *UICollectionView的简单使用可以看我以前写的这篇博文:UICollectionView的基本使用 UICollectionView与UITableView很相似,必须实现两个代理:UICollectionViewDataSource和UI…
python之文件
1、什么是文件指针? 文件指针 文件指针标记从哪个位置开始读取数据 第一次打开文件时,通常文件指针会指向文件的开始位置 当执行了read方法后,文件指针会移动到读取内容的末尾 创建一个当前目录下的文件pass 内容为: westos …

一个6年的菜鸟,在4年之前做的一些功能(二)
前戏:针对上一篇列出来的功能点,今天和大家分享下这个自定义的公式是怎么设计的,由于我的第一篇博客在首页被管理员移走了,大家可以点击这里来跳转,看下第一篇的目录结构。本人作为老菜鸟,和大家分享的也是…