SQLite基本用法

SQLite基本用法,第1张

概述依旧淡然 博客园 首页 新随笔 联系 管理 订阅 随笔- 90  文章- 0  评论- 577  Android学习笔记36:使用SQLite方式存储数据   在Android中一共提供了5种数据存储方式,分别为:   (1)Files:通过FileInputStream和FileOutputStream对文件进行 *** 作。具体使用方法可以参阅博文《Android学习笔记34:使用文件存储数据》。   依旧淡然 博客园 首页 新随笔 联系 管理 订阅 随笔- 90 文章- 0 评论- 577 Android学习笔记36:使用SQLite方式存储数据

  在AndroID中一共提供了5种数据存储方式,分别为:

  (1)files:通过fileinputStream和fileOutputStream对文件进行 *** 作。具体使用方法可以参阅博文《Android学习笔记34:使用文件存储数据》。

  (2)SharedPreferences:常用来存储键值对形式的数据,对系统配置信息进行保存。具体使用方法可以参阅博文《Android学习笔记35:使用SharedPreferences方式存储数据》。

  (3)ContentProvIDers:数据共享,用于应用程序之间数据的访问。

  (4)sqlite:AndroID自带的轻量级关系型数据库,支持sql语言,用来存储大量的数据,并且能够对数据进行使用、更新、维护等 *** 作。

  (5)Network:通过网络来存储和获取数据。

  本篇博文介绍第四种方式,通过AndroID自带的sqlite数据库存储数据。

1.sqlite简介

  sqlite是一款开源的、嵌入式关系型数据库,第一个版本Alpha发布于2000年。sqlite在便携性、易用性、紧凑性、高效性和可靠性方面有着突出的表现。

  sqlite和C/S模式的数据库软件不同,它是一款嵌入式数据库,没有独立运行的进程,与所服务的应用程序在应用程序进程空间内共生共存。它的代码与应用程序代码也是在一起的,或者说嵌入其中,作为托管它的程序的一部分。因此不存在数据库的客户端和服务器,使用sqlite一般只需要带上它的一个动态库,就可以享受它的全部功能。

  数据库服务器在程序中的好处是不需要网络配置或管理。将数据库客户端与服务器运行在同一个进程中,可以省去不少的 *** 作及麻烦:不用担心防火墙或者地址解析;不用浪费时间管理复杂的授权和权限;可以减少网络调用相关的消耗;可以简化数据库管理并使程序更容易部署。

  sqlite数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但是只有一个可以写入数据。在某个进程向数据库执行写 *** 作之前,必须获得独占锁定。在发出独占锁定后,其他的读写 *** 作将不会再发生。

  此外,sqlite数据库中的所有信息(比如表、视图、触发器等)都包含在一个文件内,方便管理和维护。sqlite数据库还支持大部分 *** 作系统,除电脑上使用的 *** 作系统之外,很多手机上使用的 *** 作系统同样可以运行。同时,sqlite数据库还提供了多语言的编程接口,供开发者使用。

2.sql基本命令

  sql是与关系型数据库通信的唯一方式。它专注于信息处理,是为构建、读取、写入、排序、过滤、映射、分组、聚集和通常的管理信息而设计的声明式语言。

  在讲解sql基本命令之前,有必要先了解一下sqlite所支持的数据类型都有哪些。

2.1sqlite支持的数据类型

  sqlite采用动态数据存储类型,会根据存入的值自动进行判断。sqlite支持以下5种数据类型:

  (1)NulL:空值

  (2)INTEGER:带符号的整型

  (3)REAL:浮点型

  (4)TEXT:字符串文本

  (5)BLOB:二进制对象

2.2sql基本命令

  表是探索sqlite中sql的起点,也是关系型数据库中信息的标准单位,所有的 *** 作都是以表为中心的。那么如何使用sql命令创建一张表呢?

2.2.1创建表

  表是由行和列组成的,列称为字段,行称为记录。

  使用CREATE命令可以创建表,CREATE命令的一般格式为:

  CREATE[TEMP/TEMPORARY]tabletable_name(column_deFinitions[,constraints]);

  其中,[]中的内容是可选的,用TEMP或TEMPORARY关键字声明的表是临时表,这种表只存活于当前会话,一旦连接断开,就会被自动销毁。如果没有明确指出创建的表是临时表,则创建的是基本表,将会在数据库中持久存在,这也是数据库中最常见的表。

  CREATEtable命令至少需要一个表名和一个字段名,上述命令中的table_name表示表名,表名必须与其他标识符不同。column_deFinitions由用逗号分隔的字段列表组成,每个字段定义包括一个名称、一个域(类型)和一个逗号分隔的字段约束。其中,域是指存储在该列的信息的类型,约束用来控制什么样的值可以存储在表中或特定的字段中。

  一条创建表的命令示例如下:

1   CREATE table tab_student (studentID INTEGER PRIMARY KEY autoINCREMENT,2                             studentname VARCHAR(20),128)">3                             studentAge INTEGER);

  如上,我们创建了一个名为tab_student的表,该表包含3个字段:studentID、studentname和studentAge,其数据类型分别为:INTEGER、VARCHAR和INTEGER。

  此外,通过使用关键字PRIMARYKEY,我们指定了字段studentID所在的列是主键。主键确保了每一行记录在某种方式上与表中的其他行记录是不同的(唯一的),进而确保了表中的所有字段都是可寻址的。

  sqlite为主键提供自增长功能,当定义字段类型为INTEGERPRIMARYKEY时,sqlite将为该字段创建默认值,该默认值确保整数值是唯一的。sqlite使用64-bit单符号整数主键,因此,该字段的最大值是9,223,372,036,854,775,807。当达到最大值时,sqlite会自动搜索该字段还未使用的值,并作为要插入的值。从表中删除记录时,rowID可能被回收并在后面的插入中使用。因此,新创建的rowID不一定是按照严格顺序增长的。如果想要sqlite使用唯一的自动主键值,而不是填补空白,可以在主键定义INTEGERPRIMARYKEY中加入关键字autoINCREMENT。autoINCREMENT关键字阻止rowID回收,它将为新插入的记录产生新的(不是回收的)rowID。

2.2.2插入记录

  使用INSERT命令可以一次插入一条记录,INSERT命令的一般格式为:

  INSERTINTOtab_name(column_List)VALUES(value_List);

  其中,tab_name指明将数据插入到哪个表中,column_List是用逗号分隔的字段名称,这些字段必须是表中存在的,value_List是用逗号分隔的值列表,这些值是与column_List中的字段一一对应的。

  比如,向刚才创建的tab_student表中插入一条记录,便可以使用如下的语句完成:


  INSERT INTO tab_student (studentID,studentname,studentAge) VALUES (1,“jack”,23);

  通过以上的语句,便插入了一条studentname=”jack”,studentAge=”23”的记录,该记录的主键为studentID=1。

2.2.3更新记录

  使用UPDATE命令可以更新表中的记录,该命令可以修改一个表中一行或者多行中的一个或多个字段。UPDATE命令的一般格式为:

  UPDATEtab_nameSETupdate_ListWHEREpredicate;

  其中,update_List是一个或多个字段赋值的列表,字段赋值的格式为column_name=value。WHERE子句使用断言识别要修改的行,然后将更新列应用到这些行。

  比如,要更新刚才插入到tab_student表中的记录,便可以使用如下的语句完成:


  UPDATE tab_student SET studentname=”tom”,studentAge=25WHERE studentID=1;

  通过以上的语句,便可以将刚才插入的主键为studentID=1的记录更新为studentname=”tom”,studentAge=”25”了。

2.2.4删除记录

  使用DELETE命令可以删除表中的记录,DELETE命令的一般格式为:

  DELETEFROMtable_nameWHEREpredicate;

  其中,table_name指明所要删除的记录位于哪个表中。和UPDATE命令一样,WHERE子句使用断言识别要删除的行。

  比如,要删除刚才插入的记录,便可以使用如下的语句完成:

  
  DELETE FROM tab_student 1;

2.2.5查询记录

  SELECT命令是查询数据库的唯一命令。SELECT命令也是sql命令中最大、最复杂的命令。

  SELECT命令的通用形式如下:

  SELECT[distinct]heading

  FROMtables

  WHEREpredicate

  GROUPBYcolumns

  HAVINGpredicate

  ORDERBYcolumns

  liMITcount,offset;

  其中,每个关键字(如FROM、WHERE、HAVING等)都是一个单独的子句,每个子句由关键字和跟随的参数构成。GROUPBY和HAVING一起工作可以对GROUPBY进行约束。ORDERBY使记录集在返回之前按一个或多个字段的值进行排序,可以指定排序方式为ASC(默认的升序)或DESC(降序)。此外,还可以使用liMIT限定结果集的大小和范围,count指定返回记录的最大数量,offset指定偏移的记录数。

  在上述的SELECT命令通用形式中,除了SELECT之外,所有的子句都是可选的。目前最常用的SELECT命令由三个子句组成:SELECT、FROM、WHERE,其基本语法形式如下:

  SELECTheadingFROMtablesWHEREpredicate;

  比如,要查询刚才插入的记录,便可以使用如下的语句完成:

  
  SELECT studentID,studentAge 1;

  至此,我们介绍了sql中最基本和最常用的CREATE、INSERT、UPDATE、DELETE和SELECT命令。当然了,这里只是对其进行了简单的介绍,有关sqlite中sql命令的详细使用方法,可以参阅《sqlite权威指南》一书的第三章和第四章。

3.数据库 *** 作辅助类sqliteOpenHelper

  AndroID提供了一个重要的类sqliteOpenHelper,用于辅助用户对sqlite数据库进行 *** 作。

  sqliteOpenHelper的构造函数原型如下:

  publicsqliteOpenHelper(Contextcontext,Stringname,sqliteDatabase.CursorFactoryfactory,intversion);

  其中,参数context表示应用程序运行的环境,包含应用程序所需的共享资源。参数name表示AndroID的数据库名字。参数factory是sqliteDatabase.CursorFactory类对象,用于存储查询AndroIDsqlite数据库的结果集。参数version表示应用程序所用的数据库的版本,该版本并非sqlite的真正版本,而是指定应用程序中的sqlite数据库的版本,当该版本号发生变化时,将会触发sqliteOpenHelper类中的onUpgrade()或onDowngrade()方法。

  sqliteOpenHelper类的所有方法如图1所示。

图1sqliteOpenHelper类的方法

  其中,close()方法用于关闭sqliteOpenHelper对象中的sqlite数据库;getReadableDatabase()方法和getWriteableDatabase()方法类似,getReadableDatabase()方法以只读状态打开sqliteOpenHelper对象中指定的sqlite数据库,任何想要修改数据库的 *** 作都是不允许的;getWriteableDatabase()方法也是打开数据库,但是允许数据库正常的读/写 *** 作;在一个不存在的数据库上调用任何方法时,都会隐式的调用sqliteOpenHelper对象的onCreate()方法;当应用程序第一次访问数据库时,则会调用onopen()方法,但是,如果版本号发生了变化的话,则会调用onUpgrade()或onDowngrade()方法。

4.数据库类sqliteDatabase

  sqliteDatabase类用来完成对数据库的 *** 作任务,比如表的选择、插入、更新和删除语句等。

  sqliteDatabase类中常用的用于执行SQL语句的方法有以下一些。

  (1)execsql()方法:

  publicvoIDexecsql(Stringsql);

  publicvoIDexecsql(Stringsql,Object[]bindArgs);

  (2)query()方法:

  publicCursorquery(Stringtable,String[]columns,Stringselection,String[]selectionArgs,String groupBy,String having,StringorderBy,Stringlimit);

  publicCursorquery(booleandistinct,Stringtable,Stringhaving,Stringlimit,CancellationSignalcancellationSignal);

  publicCursorquery(Stringtable,StringgroupBy,StringorderBy);

  publicCursorquery(booleandistinct,Stringlimit);

  (3)queryWithFactory()方法:

  publicCursorqueryWithFactory(sqliteDatabase.CursorFactorycursorFactory,booleandistinct,String orderBy,String limit,CancellationSignalcancellationSignal);

  publicCursorqueryWithFactory(sqliteDatabase.CursorFactorycursorFactory,Stringlimit);

  (4)rawquery()方法:

  publicCursorrawquery(Stringsql,CancellationSignalcancellationSignal);

  publicCursorrawquery(Stringsql,String[]selectionArgs);

  (5)rawqueryWithFactory()方法:

  publicCursorrawqueryWithFactory(sqliteDatabase.CursorFactorycursorFactory,Stringsql,String[] selectionArgs,Stringedittable);

  publicCursorrawqueryWithFactory(sqliteDatabase.CursorFactorycursorFactory,Stringedittable,CancellationSignalcancellationSignal);

  其中,execsql()方法都有一个参数sql,这个参数是一个SQL语句。第二个参数bindArgs接收一个数组,数组中的每个成员捆绑了一个查询。execsql()方法用于运行那些没有返回值的查询语句,比如创建、插入、更新和修改表。

  query()方法和queryWithFactory()方法是在数据库中运行一些轻量级的单查询语句,参数包括table、columns、groupBy、having、orderBy、limit等SQL语句关键字。这些方法允许将SQL语句传递给相关方法,而不必直接使用SQL语句。

  rawquery()方法和rawqueryWithFactory()方法也都有一个参数sql,用于执行SQL查询语句,返回值是Cursor对象。这两个方法都有一个版本能够接收一个字符串数组selectionArgs作为参数,通过这个参数,sqliteDatabase对象将把捆绑的SQL语句中的问号(?)用这个数组中的值代替,并按照一一对应的位置关系进行取代。

  sqliteDatabase类提供了大约50个方法,除此之外还有一些用于打开数据库的方法(如openDatabase()、openorCreateDatabase()等),用于管理sqlite事务的方法(如beginTransaction()、endTransaction()等),用于测试数据库是否被锁住的方法(如isDbLockedByCurrentThread()、isDbLockedByOtherThread()等),以及获取数据库基本信息的方法(如getMaximumSiza()、getVersion()等)。这里就不一一介绍了,具体可以参阅SQLiteDatabase类的API帮助文档。

5.游标类Cursor

  在AndroID中,查询数据是通过Cursor类来实现的,当我们使用sqliteDatabase.query()或sqliteDatabase.rawquery()方法时,会得到一个Cursor对象,Cursor指向的就是每一条记录,它提供了很多有关查询的方法,如图2所示。

图2Cursor类的常用方法

6.封装接口

  有了以上的基础,我们便可以按照MVC的架构,封装一个接口层,在该接口层中实现对sqlite数据库的具体 *** 作。

  以下分别以添加数据、更新数据、查询数据为例讲解其具体的实现方法。在实现这些方法之前,我们首先需要创建一张表。这里我创建了一个名为MysqLiteOpenHelper的类,让它继承自sqliteOpenHelper类,并实现了sqliteOpenHelper类的onCreate()方法,在该方法里实现创建一张表的 *** 作,具体源代码如下:

1     /*2      * Function  :    创建表3      * Author    :    博客园-依旧淡然4      */5     public voID onCreate(sqliteDatabase db) {6         db.execsql("CREATE table tab_student (studentID INTEGER PRIMARY KEY autoINCREMENT," + 
"studentname VARCHER(20)," +
"studentAge INTEGER)");7 }

  通过以上的代码,我们创建了一张名为“tab_student”的表,并在该表中创建了三个字段,分别为:studentID、studentname和studentAge。并且指定了studentID字段作为该表的主键。

6.1添加数据

  添加数据可以使用sqliteDatabase.execsql(Stringsql,Object[]bindArgs)方法来实现,具体如下:

* Function : 添加数据voID addStudentInfo(Student student) {6 db = MysqLiteOpenHelper.getWritableDatabase();7 db.execsql("INSERT INTO tab_student (studentID,studentAge) values (?,?,?)",128)">8   new Object[] {student.getStudentID(),student.getStudentname(),student.getStudentAge()});9 }

  其中,通过第二个参数bindArgs,使SQL语句中的问号(?)与这个数组中的值形成一一对应关系,从而将值写入到“tab_student”表中的对应字段中。

6.2更新数据

  更新数据的方法与添加数据的方法大致相同,具体如下:

1    /*2     * Function  :    更新数据3     * Author    :    博客园-依旧淡然4     */5    voID updateStudentInfo(Student student) {6        db = MysqLiteOpenHelper.getWritableDatabase();7        db.execsql("UPDATE tab_student SET studentname = ?,studentAge = ? WHERE studentID = ?",  new Object[] {student.getStudentname(),student.getStudentAge(),student.getStudentID()});8    }

6.3查询数据

  查询数据时,因为需要返回查询的结果,所以需要使用sqliteDatabase.rawquery()方法将查询的结果返回,具体如下:

1 2 * Function : 查询数据 3 4 5 public Student findStudentInfo(int ID) { 6 db = MysqLiteOpenHelper.getWritableDatabase(); 7 String sql = "SELECT studentID,studentAge FROM tab_student WHERE studentID = ?"; 8 Cursor cursor = db.rawquery(sql,new String[] {String.valueOf(ID)}); 9 if(cursor.movetoNext()) {10 return new Student(cursor.getInt(cursor.getColumnIndex("studentID")),
cursor.getString(cursor.getColumnIndex("studentname")),128)">11 cursor.getInt(cursor.getColumnIndex("studentAge")));12 }13 null;14 }

  可以看出,通过使用sqliteDatabase.rawquery()方法可以将查询到的结果存入Cursor对象中。然后,我们可以使用Cursor对象的getXXX()方法将查询结果从Cursor对象中取出来。

  当然了,我们还可以根据实际的需要,去实现更多的接口方法,比如,删除数据、获取数据列表、获取数据个数等等。

  封装好了以上的这些接口方法,便可以很方便的在程序中直接调用这些方法,不必再去关心底层数据库的调用,而将精力放在UI界面的设计实现上。

作者: 依旧淡然 邮箱:menlsh@163.com 博客: http://www.cnblogs.com/menlsh/ 本文版权归作者所有,未经作者同意,严禁转载及用作商业传播,否则将追究法律责任。 标签: Android 好文要顶 关注我 收藏该文 依旧淡然
关注 - 39
粉丝 - 692 +加关注 5 0 «上一篇: Android学习笔记35:使用Shared Preferences方式存储数据
»下一篇: Android学习笔记37:使用Content Providers方式共享数据
posted @ 2013-04-13 23:52 依旧淡然阅读( 16706) 评论( 4) 编辑 收藏
评论 #1楼 2013-04-14 08:58| turtlegood 好东西!!!谢谢了 支持(0) 反对(0) #2楼 2013-04-14 09:50| shungdawei 讲解的很到位 #3楼 2013-04-14 11:07| Pulp 谢谢博主的分享,在博主Android学习笔记中度过了一个美妙的周末上午 #4楼 2016-02-01 13:24| tinanuaa 你好,我想问一下如果要存储一个boolean量,应该怎么存储呢?我是要做一个闹钟的应用,其中闹钟开关还有振动开关是boolean量。目前有两种思路,一个是每一个闹钟按记录存储进数据库,另一种是把当前所有闹钟存为一个ArrayList,然后通过Gson转为string再存入数据库。前面这种方式就会遇到boolean 量无法存储的问题。我想问一下,一般会怎么做?是不是避免在数据库中存储布尔量比较好? 反对(0) 刷新评论 刷新页面 返回顶部 注册用户登录后才能发表评论,请 登录或 注册, 访问网站首页。 【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【免费】从零开始学编程,开发者专属实验平台免费实践!
最新IT新闻:
· OneDrive突然要求用户使用NTFS格式
· Google今日涂鸦以网球为主题
· 律师:乐视无法用资金担保 只能采取冻结股权的方式
· 9999元小米米家激光电视体验:玩的不是电视 是米粉
· Nvidia探索将多GPU封装到一块:轻松打破旧架构极限
» 更多新闻... 最新知识库文章:
· 小printf的故事:什么是真正的程序员?
· 程序员的工作、学习与绩效
· 软件开发为什么很难
· 唱吧DevOps的落地,微服务CI/CD的范本技术解读
· 程序员,如何从平庸走向理想?
» 更多知识库文章... 昵称: 依旧淡然
园龄: 4年11个月
粉丝: 692
关注: 39 +加关注
< 2013年4月 >
31 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 1 2 3 4
5 6 7 8 9 10 11
搜索 常用链接 我的随笔 我的评论 我的参与 最新评论 我的标签 更多链接 我的标签 Android(52) 个人日志(10) 【VC++技术杂谈】(8) Windows编程(5) Java(3) 设计模式(3) linux(2) QT(2) 【玩转单片机系列】(2) Android源码解析(1) 更多 随笔档案 2015年5月 (1) 2015年4月 (2) 2015年1月 (3) 2014年12月 (3) 2014年6月 (1) 2013年6月 (4) 2013年5月 (7) 2013年4月 (8) 2013年3月 (11) 2013年2月 (8) 2013年1月 (15) 2012年12月 (6) 2012年11月 (9) 2012年10月 (6) 2012年8月 (1) 2012年7月 (5) 积分与排名 积分 - 202123 排名 - 1006 最新评论 1. Re:【玩转单片机系列002】 如何使用STM32提供的DSP库进行FFT 最近想做拿32做一个雷达数据处理的模块。先借鉴一下。谢谢 --jason_nuc 2. Re:串口通信与编程01:串口基础知识 不错! --美洲象 3. Re:【VC++技术杂谈003】打印技术之打印机状态监控 请问下,你是怎么监听的?使用轮询?还是有事件触发? --沙漠俊 4. Re:Android学习笔记46:使用Post方式提交数据 httpUtils是重新创建了个类还是? --南门 5. Re:Android学习笔记46:使用Post方式提交数据 安卓客户端的点击按钮点击之后服务器端完全没反应,别的地方都没问题 --南门 阅读排行榜 1. Android学习笔记46:使用Post方式提交数据(56814) 2. Android学习笔记23:时间日期控件的使用(56120) 3. 串口通信与编程01:串口基础知识(51727) 4. Win7下VS2008破解方法(40255) 5. Android学习笔记27:网格视图GridView的使用(37648) 6. Android学习笔记45:JSON数据解析(GSON方式)(37479) 7. Android学习笔记49:Socket编程实现简易聊天室(37315) 8. Android学习笔记09:Paint及Canvas的简单应用(30929) 9. Android学习笔记25:画廊控件Gallery的使用(22754) 10. 修改linux终端命令行颜色(22193) 评论排行榜 1. 2012,写给24岁的自己(314) 2. Android学习笔记49:Socket编程实现简易聊天室(42) 3. Android学习笔记46:使用Post方式提交数据(34) 4. 【玩转单片机系列001】 08接口双色LED显示屏驱动方式探索(33) 5. 【VC++技术杂谈005】如何与程控仪器通过GPIB接口进行通信(10) 6. 【玩转单片机系列002】 如何使用STM32提供的DSP库进行FFT(9) 7. Android学习笔记30:列表ListView控件的使用(8) 8. Android学习笔记31:使用惰性控件ViewStub实现布局动态加载(7) 9. Android学习笔记44:JSON数据解析(7) 10. 【VC++技术杂谈003】打印技术之打印机状态监控(5) 推荐排行榜 1. 2012,写给24岁的自己(87) 2. Android学习笔记49:Socket编程实现简易聊天室(10) 3. Android学习笔记46:使用Post方式提交数据(7) 4. 串口通信与编程01:串口基础知识(7) 5. Android学习笔记45:JSON数据解析(GSON方式)(6) 6. 【玩转单片机系列001】 08接口双色LED显示屏驱动方式探索(5) 7. 【VC++技术杂谈004】使用微软TTS语音引擎实现文本朗读(5) 8. Android学习笔记36:使用SQLite方式存储数据(5) 9. Android学习笔记10:TextView的使用(5) 10. Win7下VS2008破解方法(5) @H_149_1419@ copyright ©2017 依旧淡然 总结

以上是内存溢出为你收集整理的SQLite基本用法全部内容,希望文章能够帮你解决SQLite基本用法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1163146.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存