[原创] Xcode中使用sqlite3访问数据库

  最近开始写博客了,把我学习到的东西进行汇总和总结,今天就说说怎么使用sqlite3来操纵数据库吧   

  数据库的相关知识我就不去说明了,毕竟只要会sql语言的人就大家都一样。

  本案例是在Xcode环境下创建的single view application进行演示操作,如有不清楚的朋友可以找我下载代码。qq:1750587828.

  首先第一点,为什么要使用sqlite3?   

  在iOS的编程中,毫无疑问接触最多的就是界面的代码编排和设计,数据的解析与放置,算法的各种挠头问题。。。   在数据的解析与放置这一块,就会涉及到数据库缓存的操作,我们都知道,iOS手机编程是在手机端运行的,你不能老是去服务器端读取数据啊,好,就算你不烦,手机也跑的起来,流量不要过啊,对于手机控或者应用使用者来说,流量就是生命,而且,如果总是去服务器端读取数据,对手机的运行速度也会有影响,毕竟有一个网络传输的过程,所以,为了让用户有一个更好的体验,一般建议的做法是,将服务器的数据进行下载,然后通过数据库缓存起来,这样就不用每次每次的去请求服务器数据了,如果在数据库中有的数据,直接可以通过数据库查询得到,而省去了一次甚至多次的服务器请求操作。而sqlite3就是提供了一种C语言的访问数据库的形式。之后我们的代码会看到,其实sqlite3的语法可能比较难以理解,不过,我也会给大家来进行介绍的。      

  那么第二点,使用sqlite3的好处是什么?

  使用sqlite3的好处么,除开语法的各种蛋疼之外,访问的速度还是会比FMDB快一些的。而且,随着一步步的汇总和总结,你可以清晰的知道每一句sqlite3的语句的作用,而不是使用封装好了的语句,只要用就可以了,但是不知道是为什么。我个人觉得,学习学习吧,还是要知其然,亦知其所以然这样才能学的踏实。   

  第三点,让我们来开始学习sqlite3的使用方式吧:  

  3.1 第一步,引入sqlite3库,并在使用sqlite3的地方导入sqlite3.

   

  3.2 第二步,创建sqlite数据库文件   

  sqlite3提供的是一种访问操纵数据库的形式,那么,如果想要使用sqlite3来访问操纵数据库,首先我们得先有个数据库,下面就是一句代码生成一个数据库文件。

/*得到数据库文件地址,这是一个拼接的地址字符串,是沙盒路径下面的shop.sqlite文件,

这个文件名可以随便取名字,后缀最好是db啊或者sqlite这种,用来表示这是一个数据库文件*/

NSString* filename=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"shop.sqlite"];

/*sqlite3_open是我们接触到的第一条sqlite3语句,它的作用时打开数据库连接,如果有数据库文件就打开它,没有就重新创建数据库,这个方法有一个枚举的返回值表示是否正常打开了数据库,我用int的变量status去接收了这个值,后面会进行判断。

sqlite3_open有两个参数,第一个参数是数据库文件的路径,第二个参数是一个数据库的引用,即一个sqlite3*类型的引用;

filename.UTF8String:filename本身是oc的字符串类型,但是sqlite3_open要求传递的是C类型的字符串,所以,使用UTF8String将oc的字符串类型转换为C类型的字符串

*/

int status=sqlite3_open(filename.UTF8String, &_shop);

if(status == SQLITE_OK)//枚举值SQLITE_OK,代表成功的状态

{

    NSLog(@"打开数据库成功");

  }

else

NSLog(@"打开数据库失败");

  3.3 创建数据库表

  当我们打开了数据库连接的时候,表示在程序的沙盒路径下已经创建了一个shop.sqlite的数据库文件,而这个数据库里现在什么东西都没有,我们需要创建一张数据库表来存放数据。在这里我就封装一个setupTable来进行创建表的操作。

-(void) setupTable
{

     //创表语句,IF NOT EXISTS防止创建重复的表,AUTOINCREMENT是自动增长关键字,real是数字类型

const char * sql="CREATE TABLE IF NOT EXISTS t_shop(id integer PRIMARY KEY AUTOINCREMENT,name text NOT NULL,price real);";

//保存错误信息的变量

char * errMsg=NULL;

    /*sqlite3_exec是我们接触到的第二个sqlite3语句,这个语句用于执行除了查询语句以外的其他语句.

    它有一个枚举类型的返回值,和sqlite3_open返回的枚举值一致,这里我并没有使用变量保存,因为我有其他形式来获得创建表是否成功。

    sqlite3_exec需要传递5个参数,第一个参数是数据库引用即sqlite3* _shop,第二个参数是要执行的sql语句,

    第三个参数是执行完sql语句后要执行的函数,第四个参数是执行完sql语句后要执行的函数的参数,第五个参数是执行完sql语句后的报错信息。

  */

sqlite3_exec(_shop, sql, NULL, NULL, &errMsg);

if(errMsg)//如果存在报错信息,代表语句执行失败,比判断枚举值要更简单一些

{

NSLog(@"创建表shop失败-%s",errMsg);//打印错误信息

}

}

  3.4 封装数据库连接和创建数据库表

-(void)setupDB

{

//得到数据库文件地址

NSString* filename=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"shop.sqlite"];

//NSLog(@"%@",filename);

//打开数据库连接,如果有就打开,没有就重新创建连接

int status=sqlite3_open(filename.UTF8String, &_shop);

if(status == SQLITE_OK)

{

NSLog(@"打开数据库成功");

//创表语句

[self setupTable];

}

else

{

NSLog(@"打开数据库失败");

}

}

  3.5 数据表操纵

  所谓的数据表操纵即是对数据表中数据的增删改,也是最经常会使用到的功能。即执行insert,update,delete语句。

- (IBAction)add:(id)sender {//这里是一个按钮的点击提供的新增功能

/*拼接插入数据的sql语句*/

NSString * sql=[NSString stringWithFormat:@"INSERT INTO t_shop(name,price) VALUES(‘%@‘,%f)",self.name.text,self.price.text.doubleValue];

char* errMsg=NULL;

sqlite3_exec(self.shop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

{

NSLog(@"插入数据失败--%s",errMsg);

}

}

-(void)updateData//这里是一个方法提供了更新功能

{

 //拼接sql更新语句

NSString * sql=[NSString stringWithFormat:@"update t_shop set name=‘%@‘,price=‘%@‘ where id=%@",self.name.text,self.price.text,self.lbl.text];

//NSLog(@"%@",sql);

char* errMsg=NULL;

sqlite3_exec(self.myShop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

{

NSLog(@"更新数据失败--%s",errMsg);

}

}

-(void)deleteDataById:(int)pid

{//提供一个方法执行删除操作,该方法要求得到要删除的数据的id

  //拼接sql删除语句

NSString * sql=[NSString stringWithFormat:@"DELETE FROM t_shop where id=%d",pid];

char* errMsg=NULL;

sqlite3_exec(self.shop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

{

NSLog(@"删除数据失败--%s",errMsg);

}

}

  大家可以观察上面的三个方法,会发现除了sql语句的拼接不一样以外,其他的地方几乎一模一样,所以,增删改的操作相对来说还是比较简单的。

  3.6 查询数据 

/**

*  查询数据

*/

-(void)setupData

{

const char * sql="select * from t_shop";//查询sql语句

//stmt用来取出查询结果

sqlite3_stmt *stmt=NULL;

/*sqlite3_prepare_v2函数是准备要执行sql查询的一个函数,可以当做这个函数就是用来做sql查询之前的准备工作的,

  它也是返回一个枚举作为准备工作的结果,SQLITE_OK则代表准备工作ok

  sqlite3_prepare_v2需要传入5个参数,第一个参数是数据库引用即(sqlite3* _shop),第二个参数是要执行的sql语句,第三个参数是sql语句的长度

  第四个参数是查询结果stmt的引用,查询完成后,查询结果将会存入该引用,第五个参数是指向无法使用的部分的指针,一般不会用到,给NULL就可以了

  */

int status = sqlite3_prepare_v2(_shop, sql, -1, &stmt, NULL);

if(status == SQLITE_OK)//准备成功,SQL语句正确

{

  /*sqlite3_step(stmt)函数将会执行查询并且将查询到的当前记录存入到stmt(sqlite3_stmt * 类型)中

    第一次执行sqlite3_step(stmt)将会将表中的第一条数据存入到stmt中,第二次执行sqlite3_step(stmt)将会把表中的第二条记录存入到stmt中

  也就是说,while(sqlite3_step(stmt)==SQLITE_ROW)将会一条一条的去读取表中的记录,而SQLITE_ROW枚举判断的是有读取到数据行的情况*/

while(sqlite3_step(stmt) == SQLITE_ROW)//成功指向一条记录

{

Shop* shop=[[Shop alloc]init];//封装的实体

    /*sqlite3_column_xxxx函数:它用来读取数据行中不同类型的数据,该函数的返回值就是读取到得数据内容,

      该函数需要2个参数,第一个参数是存放数据的stmt,第二个参数是数据列下标*/

shop.pid= sqlite3_column_int(stmt, 0);//读取stmt中存储的第0列数据

const char* pname= (const char*)sqlite3_column_text(stmt, 1);//读取stmt中存储的第1列数据

const char* pprice = (const char*)sqlite3_column_text(stmt, 2);//读取stmt中存储的第2列数据

shop.name = [NSString stringWithUTF8String:pname];//将C类型的字符串转换为oc类型的字符串并存储

shop.price = [NSString stringWithUTF8String:pprice];//将C类型的字符串转换为oc类型的字符串并存储

//NSLog(@"编号:%d,商品名:%s,价格:%s",shop.pid,pname,pprice);

}

}

}

  那么,写到这里,相信大家对sqlite3的基本使用已经有了大致的了解,如果对代码中有不理解的地方,或者有其他相关的问题,可以找我一起来研究讨论。

  第一次发博客,希望大家提出宝贵的意见和建议,编程路上,与你同行。

时间: 2024-08-03 09:36:30

[原创] Xcode中使用sqlite3访问数据库的相关文章

Python中通过cx_Oracle访问数据库遇到的问题总结

以下是Python中通过cx_Oracle操作数据库的过程中我所遇到的问题总结,感谢我们测试组的前辈朱勃给予的帮助最终解决了下列两个问题: 1)安装cx_Oracle会遇到的问题:在Windows下安装cx_Oracle不要尝试用pip install的方式了!下载官网的对应版本的msi安装文件,我的python2.7是32位的,oracle的instantClient也是32位的,这个cx_Oracle也选择32位的下载,安装成功后进入python模式下import cx_Oracle没问题,

springmvc框架的项目,如何在controller中使用dao访问数据库

在springmvc框架中,controller和其他的bean是被分别扫描的,原因是如果不这样配置,controller就会被扫描两次,从而导致事物等问题. 通常情况下,controller是不允许直接使用dao的,一个合理的设计就是在sevice中去调用dao. 但是如果有临时的需求需要在controller中访问数据库,那怎么办呢? 有两种方法. 方法1:在web.xml中配置,使spring对事物的控制设计请求的整个生命周期. <!--配置Spring的OpenSessionInView

企业分布式微服务云SpringCloud SpringBoot mybatis (七)Spring Boot中使用JdbcTemplate访问数据库

本文介绍在Spring Boot基础下配置数据源和通过JdbcTemplate编写数据访问的示例. 数据源配置 在我们访问数据库的时候,需要先配置一个数据源,下面分别介绍一下几种不同的数据库配置方式. 首先,为了连接数据库需要引入jdbc支持,在pom.xml中引入如下配置: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdb

在java中使用JDBC访问数据库

配置文件之类的加略过了 1:首先需要创建一个类: //写入以上代码,上面的代码很难记所以手打会很容易出错,我们可以从配置文件中找到字符串,当链接数据库成功之后,就可以进行增删改查了. 其中修改添加,删除都可以使用executeupdate方法,在这里就不一一列举了 这是数据库中的新增结果 下面是查询的代码: 查询使用的是executequery方法 当我们做完这些工作之后要记得关闭连接,那个后开加就先关闭那个 这是查询后的结果

JSP中通过JDBC访问数据库

一.步骤介绍 1.通过Class.forName()加载驱动: 2.通过DriverManager.getConnection()获取Conncetion连接对象: 3.创建Statement对象传递sql语句到数据库执行: 4.接收ResultSet查询结果: 5.释放资源. 二.查询案例 public void getData(){ String URL = "jdbc:sqlserver://127.0.0.1:1433;databaseName=news"; Connectio

[原创]使用FMDB的访问数据库

最近开始写博客了,把我学习到的东西进行汇总和总结. 今天复习到FMDB,FMDB是一个第三方的访问数据库的插件.有了它以后,妈妈再也不用担心我访问数据库的问题. 好了,言归正传,为什么要使用FMDB呢? 最直接的一个原因就是,iOS中的sqlite3访问数据库的代码太过繁琐,难记,写起来也不顺手,究其原因非常简单,就是sqlite3是C封装的一个访问数据库的api,它是用C写的,你想用也要用C的形式去访问,所以,使用起来你会觉得有点变扭,就好像是一个生活在广东的外地人,虽然也可以和广东人交流,但

访问内网中的sql server数据库的简便方法

前言: 有时候我们要访问局域网内的 sql server服务器,比如测试环境数据库在公司内网,回到家或在客户现场要连接内网中的数据库 第一步:假如可以连接局域网的数据库 192.168.150.129 ,在远程还要能连接它 第二步:在内网穿山甲中添加一个TCP端口,本机IP填局域网的IP,端口 1433,映射到外网端口 随便填 然后就可以用 yxnat.softdev.top,7777 访问内网中的sql server数据库了 数据库连接配置文件中也可以这填上端口号就可以连接 YXNAT.Sof

2014-07-30 MVC框架中对SQL Server数据库的访问

今天是在吾索实习的第16天.我自己主要学习了基于MVC框架的系统的开发时,对SQL Server数据库的相关访问.其步骤如下: 第一步,在Models文件夹中创建一个类,并命名为Movies.cs,如图1所示: 图1 第二步,在上述Movies.cs文件中的namespace MvcTest.Models{}中输入如下代码: 1 public class Movie 2 { 3 public int ID { get; set; } 4 public string Title { get; se

web api中访问数据库的内存释放问题

在使用web api开发微信后台的时候,本来想像MVC一样在controller中申明dbcontext全局变量,其它地方直接使用就可以了,结果调试过程中发现使用dbcontext访问数据库并获取query后,如果不使用asenumerable或者tolist强制断开与数据库的链接,那么非常容易出现out of system memory的错误,我觉得是内存一直没有释放的问题.后来我把dbcontext的全局变量去掉,在需要使用的时候使用using(var d = new dbcontext()