一、关系型数据库SQLIte

每个应用程序都要使用数据,Android应用程序也不例外,Android使用开源的、与操作系统无关的SQL数据库—SQLite。SQLite第一个Alpha版本诞生于2000年5月,它是一款轻量级数据库,它的设计目标是嵌入式的,占用资源非常的低,只需要几百K的内存就够了。SQLite已经被多种软件和产品使用,Mozilla FireFox就是使用SQLite来存储配置数据的,Android和iPhone都是使用SQLite来存储数据的。

SQLite体系结构图如下:

Android创建和使用数据库_第1张图片    

  编译器包括Tokenizer(词法分析器)、 Parser(语法分析器)、Code Generator(代码产生器)。他们协同处理文本形式的结构化查询语句。

  后端由B-tree,Pager,OS Interface组成。B-tree的职责是负责排序,维护多个数据库页之间错综复杂的关系,将页面组织成树状结构,页面就是树的叶子。Pager负责传输,根据B-tree的请求从磁盘读取页面或者写入页面。

  公共服务中有各种实用的功能比如:内存分配、字符串比较,Unicode转换等。

SQLite数据库是D.Richard Hipp用C语言编写的开源嵌入式数据库,支持的数据库大小为2TB。它具有如下特征:

1、轻量级

SQLite和C\S模式的数据库软件不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态库,就可以享受它的全部功能。而且那个动态库的尺寸也相当小。

2、独立性

SQLite数据库的核心引擎本身不依赖第三方软件,使用它也不需要“安装”,所以在使用的时候能够省去不少麻烦。

3、隔离性

SQLite数据库中的所有信息(比如表、视图、触发器)都包含在一个文件内,方便管理和维护。

4、跨平台

SQLite数据库支持大部分操作系统,除了我们在电脑上使用的操作系统之外,很多手机操作系统同样可以运行,比如Android、Windows Mobile、Symbian、Palm等。

5、多语言接口

SQLite数据库支持很多语言编程接口,比如C\C++、Java、Python、dotNet、Ruby、Perl等,得到更多开发者的喜爱。

6、安全性

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

SQLite官方网站(http://www.sqlite.org),了解更多内容请前往。

二、导出查看数据库文件

  在android中,为某个应用程序创建的数据库,只有它可以访问,其它应用程序是不能访问的,数据库位于Android设备/data/data/package_name/databases文件夹中。

  想要将数据库文件导出可以使用eclipse,如图所示:

Android创建和使用数据库_第2张图片

  查看数据库,使用SQlite Database Browser,如图所示:

Android创建和使用数据库_第3张图片

三、扩展类

3.1扩展SQLiteOpenHelper

  Android 不自动提供数据库。在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。Android 提供了 SQLiteOpenHelper 帮助你创建一个数据库,你只要继承 SQLiteOpenHelper 类,就可以轻松的创建数据库。SQLiteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。SQLiteOpenHelper 的子类,至少需要实现三个方法:

  构造函数,调用父类 SQLiteOpenHelper 的构造函数

  onCreate()方法;// TODO 创建数据库后,对数据库的操作

  onUpgrage()方法。// TODO 更改数据库版本的操作

  当你完成了对数据库的操作(例如你的 Activity 已经关闭),需要调用 SQLiteDatabase 的 Close() 方法来释放掉数据库连接。

  操作数据库的最佳实践是创建一个辅助类,例如联系人模块

  class ContactsDatabaseHelper extends SQLiteOpenHelper

3.2 Cursor类

  Android使用Cursor类返回一个需要的值,Cursor作为一个指针从数据库查询返回结果集,使用Cursor允许Android更有效地管理它们需要的行和列,你使用ContentValues对象存储键/值对,它的put()方法允许你插入不同数据类型的键值。

3.3 数据类型

  SQLite 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 CREATE TABLE 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,SQLite 将检查它的类型。如果该类型与关联的列不匹配,则 SQLite 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(String)放入 INTEGER 列。SQLite 称这为“弱类型”(manifest typing.)。 四、数据库操作

4.1创建数据库
Android 不自动提供数据库。在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。Android 提供了 SQLiteOpenHelper 帮助你创建一个数据库,你只要继承 SQLiteOpenHelper 类,就可以轻松的创建数据库。SQLiteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。SQLiteOpenHelper 的子类,至少需要实现三个方法:
构造函数,调用父类 SQLiteOpenHelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 Activity),数据库名字,一个可选的游标工厂(通常是 Null),一个代表你正在使用的数据库模型版本的整数。
onCreate()方法,它需要一个 SQLiteDatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。
onUpgrage() 方法,它需要三个参数,一个 SQLiteDatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。

下面示例代码展示了如何继承 SQLiteOpenHelper 创建数据库:

public class DatabaseHelper extends SQLiteOpenHelper {      DatabaseHelper(Context context, String name, CursorFactory cursorFactory, int version)  {        super(context, name, cursorFactory, version);         }              @Override        public void onCreate(SQLiteDatabase db) {             // TODO 创建数据库后,对数据库的操作         }              @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {             // TODO 更改数据库版本的操作         }          @Override    public void onOpen(SQLiteDatabase db) {             super.onOpen(db);               // TODO 每次成功打开数据库后首先被执行         }     }     

接下来讨论具体如何创建表、插入数据、删除表等等。调用 getReadableDatabase() 或 getWriteableDatabase() 方法,你可以得到 SQLiteDatabase 实例,具体调用那个方法,取决于你是否需要改变数据库的内容:

db=(new DatabaseHelper(getContext())).getWritableDatabase(); return (db == null) ? false : true; 

上面这段代码会返回一个 SQLiteDatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。

当你完成了对数据库的操作(例如你的 Activity 已经关闭),需要调用 SQLiteDatabase 的 Close() 方法来释放掉数据库连接。

4.2创建表和索引

为了创建表和索引,需要调用 SQLiteDatabase 的 execSQL() 方法来执行 DDL 语句。如果没有异常,这个方法没有返回值。

例如,你可以执行如下代码:

db.execSQL("CREATE TABLE mytable (_id INTEGER PRIMARY KEY          AUTOINCREMENT, title TEXT, value REAL);"); 

这条语句会创建一个名为 mytable 的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数(例如,当你插入一行时,SQLite 会给这列自动赋值),另外还有两列:title( 字符 ) 和 value( 浮点数 )。 SQLite 会自动为主键列创建索引。

通常情况下,第一次创建数据库时创建了表和索引。如果你不需要改变表的 schema,不需要删除表和索引 . 删除表和索引,需要使用 execSQL() 方法调用 DROP INDEX 和 DROP TABLE 语句。

4.3给表添加数据

上面的代码,已经创建了数据库和表,现在需要给表添加数据。有两种方法可以给表添加数据。

像上面创建表一样,你可以使用 execSQL() 方法执行 INSERT, UPDATE, DELETE 等语句来更新表的数据。execSQL() 方法适用于所有不返回结果的 SQL 语句。例如:

db.execSQL("INSERT INTO widgets (name, inventory)"+ "VALUES ('Sprocket', 5)"); 

另一种方法是使用 SQLiteDatabase 对象的 insert(), update(), delete() 方法。这些方法把 SQL 语句的一部分作为参数。示例如下:

ContentValues cv=new ContentValues(); cv.put(Constants.TITLE, "example title"); cv.put(Constants.VALUE, SensorManager.GRAVITY_DEATH_STAR_I); db.insert("mytable", getNullColumnHack(), cv); 

update()方法有四个参数,分别是表名,表示列名和值的 ContentValues 对象,可选的 WHERE 条件和可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记。update() 根据条件,更新指定列的值,所以用 execSQL() 方法可以达到同样的目的。

WHERE 条件和其参数和用过的其他 SQL APIs 类似。例如:

String[] parms=new String[] {"this is a string"}; db.update("widgets", replacements, "name=?", parms); 

delete() 方法的使用和 update() 类似,使用表名,可选的 WHERE 条件和相应的填充 WHERE 条件的字符串。

4.3查询数据库

类似 INSERT, UPDATE, DELETE,有两种方法使用 SELECT 从 SQLite 数据库检索数据。

1 .使用 rawQuery() 直接调用 SELECT 语句;

使用 query() 方法构建一个查询。

Raw Queries

正如 API 名字,rawQuery() 是最简单的解决方法。通过这个方法你就可以调用 SQL SELECT 语句。例如:

Cursor c=db.rawQuery(     "SELECT name FROM sqlite_master WHERE type='table' AND name='mytable'",

在上面例子中,我们查询 SQLite 系统表(sqlite_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。

如果查询是动态的,使用这个方法就会非常复杂。例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。

Regular Queries

query() 方法用 SELECT 语句段构建查询。SELECT 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP BY 条件,HAVING 条件。

除了表名,其他参数可以是 null。所以,以前的代码段可以可写成:

String[] columns={"ID", "inventory"}; String[] parms={"snicklefritz"}; Cursor result=db.query("widgets", columns, "name=?",parms, null, null, null); 

使用游标

不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 SQLite 数据库游标,使用游标,你可以:

通过使用 getCount() 方法得到结果集中有多少记录;

通过 moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍历所有记录;

通过 getColumnNames() 得到字段名;

通过 getColumnIndex() 转换成字段号;

通过 getString(),getInt() 等方法得到给定字段当前记录的值;

通过 requery() 方法重新执行查询得到游标;

通过 close() 方法释放游标资源;

例如,下面代码遍历 mytable 表

Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");    result.moveToFirst();    while (!result.isAfterLast()) {        int id=result.getInt(0);        String name=result.getString(1);        int inventory=result.getInt(2);        // do something useful with these        result.moveToNext();      }      result.close(); 

在 Android 中使用 SQLite 数据库管理工具

在其他数据库上作开发,一般都使用工具来检查和处理数据库的内容,而不是仅仅使用数据库的 API。使用 Android 模拟器,有两种可供选择的方法来管理数据库。

首先,模拟器绑定了 sqlite3 控制台程序,可以使用 adb shell 命令来调用他。只要你进入了模拟器的 shell,在数据库的路径执行 sqlite3 命令就可以了。数据库文件一般存放在:

/data/data/your.app.package/databases/your-db-name

如果你喜欢使用更友好的工具,你可以把数据库拷贝到你的开发机上,使用 SQLite-aware 客户端来操作它。这样的话,你在一个数据库的拷贝上操作,如果你想要你的修改能反映到设备上,你需要把数据库备份回去。

把数据库从设备上考出来,你可以使用 adb pull 命令(或者在 IDE 上做相应操作)。存储一个修改过的数据库到设备上,使用 adb push 命令。

一个最方便的 SQLite 客户端是 FireFox SQLite Manager 扩展,它可以跨所有平台使用。

图 2. SQLite Manager

Android创建和使用数据库_第4张图片

五、实际应用

 Android在运行时集成了SQLite , 所以每个Android应用程序都可以使用SQLite数据库。

  数据库存放的位置:data/<项目文件夹>/databases/

  第一步:创建数据库

  Android 中提供SQLiteOpenHelper类帮助创建一个数据库,继承该类可以轻松的创建SQLite数据库;

  注意:SQLiteOpenHelper的子类至少要实现三个方法:

  * 带参的构造方法;

  * onCreate();

  * onUpgrag();

  java代码如下:

package com.example.sqlite;  import android.content.Context;  import android.database.sqlite.SQLiteDatabase;  import android.database.sqlite.SQLiteDatabase.CursorFactory;  import android.database.sqlite.SQLiteOpenHelper;  /* SQLiteOpenHelper的子类, 用于操作数据库  *  * SQLiteOpenHelper 是一个辅助类,用来管理数据库的创建和版本,提供两方面的功能;  *  * 第一:getReadableDatabase() 、 getWriteableDatabase() 可以获得SQLiteDatabase对象,通过该对象可以对数据库进行操作;  *  * 第二:提供onCreate() ; onUpgrade() 两个回调函数,允许我们再创建和删除数据库时,进行自己的操作;  *  * */  public class MySQLiteOpenHelper extends SQLiteOpenHelper {  /* 构造方法,调用父类SQLiteOpenHelper的构造函数 */  /* 参1:上下文环境;参2:数据库名称(以.db结尾) ; 参3:游标工厂(默认为null) ; 参4:代表使用数据库模型版本的证书*/  public MySQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {  super(context, name, factory, version);  }  /* 根据需要对SQLiteDatabase 的对象填充表和数据初始化 */  /* 该方法时在第一次创建的时候执行,实际上时第一次得到SQLiteDatabase对象的时侯才会调用这个方法 */  public void onCreate(SQLiteDatabase db) {  // TODO 创建数据库后,对数据库的操作  }  /* 将数据库从旧的模型转换为新的模型 *//* 参1:对象 ; 参2:旧版本号 ; 参3:新版本号 */  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  // TODO 更改数据库版本的操作  }  /* 打开数据库执行的函数 */  public void onOpen(SQLiteDatabase db) {  // TODO 每次成功打开数据库后首先被执行  super.onOpen(db);  }  }  package com.example.sqlite;  import android.content.Context;  import android.database.sqlite.SQLiteDatabase;  import android.database.sqlite.SQLiteDatabase.CursorFactory;  import android.database.sqlite.SQLiteOpenHelper;  /* SQLiteOpenHelper的子类, 用于操作数据库  *  * SQLiteOpenHelper 是一个辅助类,用来管理数据库的创建和版本,提供两方面的功能;  *  * 第一:getReadableDatabase() 、 getWriteableDatabase() 可以获得SQLiteDatabase对象,通过该对象可以对数据库进行操作;  *  * 第二:提供onCreate() ; onUpgrade() 两个回调函数,允许我们再创建和删除数据库时,进行自己的操作;  *  * */  public class MySQLiteOpenHelper extends SQLiteOpenHelper {  /* 构造方法,调用父类SQLiteOpenHelper的构造函数 */  /* 参1:上下文环境;参2:数据库名称(以.db结尾) ; 参3:游标工厂(默认为null) ; 参4:代表使用数据库模型版本的证书*/  public MySQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {  super(context, name, factory, version);  }  /* 根据需要对SQLiteDatabase 的对象填充表和数据初始化 */  /* 该方法时在第一次创建的时候执行,实际上时第一次得到SQLiteDatabase对象的时侯才会调用这个方法 */  public void onCreate(SQLiteDatabase db) {  // TODO 创建数据库后,对数据库的操作  }  /* 将数据库从旧的模型转换为新的模型 *//* 参1:对象 ; 参2:旧版本号 ; 参3:新版本号 */  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  // TODO 更改数据库版本的操作  }  /* 打开数据库执行的函数 */  public void onOpen(SQLiteDatabase db) {  // TODO 每次成功打开数据库后首先被执行  super.onOpen(db);  }  }

案例代码如下:

package com.example.sqlite;  import android.app.Activity;  import android.content.ContentValues;  import android.database.Cursor;  import android.database.sqlite.SQLiteDatabase;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.Toast;  public class MainActivity extends Activity {  /* 设置表相关信息的常量 */  final String MYTAB = "t_score";  final String MYNAME ="name";  final String MYSCORE = "score";  MySQLiteOpenHelper helper;  private Button selectData,createDatabase,createTable,insertData,updateData,deleteData;  /* 获取组建对象 */  public void init(){  selectData = (Button) findViewById(R.id.selectData);  createDatabase = (Button) findViewById(R.id.createDatabase);  createTable = (Button) findViewById(R.id.createTable);  insertData = (Button) findViewById(R.id.insertData);  updateData = (Button) findViewById(R.id.updateData);  deleteData = (Button) findViewById(R.id.deleteData);  }  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  /* 初始化组件对象 */  init();  /* 创建数据库 */  createDatabase.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 创建一个MySQLiteOpenHelper,该语句执行是不会创建或打开连接的 */  helper = new MySQLiteOpenHelper(MainActivity.this, "mydb.db", null, 1);  /* 调用MySQLiteOpenHelper的getWriteableDatabase()方法,创建或者打开一个连接 */  SQLiteDatabase sqlitedatabase = helper.getWritableDatabase();  Toast.makeText(MainActivity.this, "数据库创建成功", 1000).show();  }  });  /* 创建表 */  createTable.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 创建一个MySQLiteOpenHelper,该语句执行是不会创建或打开连接的 */  helper = new MySQLiteOpenHelper(MainActivity.this, "mydb.db", null, 1);  /* 获取一个可写的SQLiteDatabase对象,创建或打开连接 */  SQLiteDatabase sqliteDatabase = helper.getWritableDatabase();  /* 创建两张表 */  sqliteDatabase.execSQL("create table student(id INTEGER PRIMARY KEY autoincrement,name text);");  sqliteDatabase.execSQL("create table "+MYTAB+"("+MYNAME+" text,"+MYSCORE+" integer);");  /* 小贴士 */  Toast.makeText(MainActivity.this, "数据表创建成功", 1000).show();  }  });  /* 插入数据 */  insertData.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 连接数据库 *//* 数据库中有表 , 对表进行操作 */  SQLiteDatabase sqliteDatabase = helper.getWritableDatabase();  /* 给表添加数据: *//* 方式1: *//* 增加一条数据 */  sqliteDatabase.execSQL("insert into student(name) values('mike')");  /* 方式2: *//* 使用SQLiteDatabase 对象的insert()方法 */  /* 创建ContentValues对象 *//* 每次插入的时一条数据 */  ContentValues cv = new ContentValues();  cv.put("name", "mary"); /* key==列 value==值 */  sqliteDatabase.insert("student", null, cv);  cv.clear();  /* 对MYTAB进行数据添加 */  sqliteDatabase.execSQL("insert into "+MYTAB+" values('ray',95)");  sqliteDatabase.execSQL("insert into "+MYTAB+" values('tom',85)");  sqliteDatabase.execSQL("insert into "+MYTAB+" values('jone',90)");  cv.put(MYNAME, "jack");  cv.put(MYSCORE, 78);  sqliteDatabase.insert(MYTAB, null, cv);  cv.clear();  Toast.makeText(MainActivity.this, "数据插入成功", 1000).show();  }  });  /* 修改数据 *//* updateData点击事件监听器 */  updateData.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 建立和数据库的连接,获取SQLiteDatabase对象 */  SQLiteDatabase sqliteDatabase = helper.getWritableDatabase();  /* 方式1:直接使用语句 */  //sqliteDatabase.execSQL("update student set name='mary key' where id=1");  /* 方式2:使用sqliteDatabase.update();方法 */  ContentValues cv = new ContentValues();  cv.put("name", "mary key"); /* 确定需要修改对应列的值 */  /* 参1:表名 ; 参2:ContentValues对象; 参3:where字句,相当于sql中where后面的语句,?是占位符 */  /* 参4:占位符的值; */  sqliteDatabase.update("student", cv, "id=?", new String[]{"1"});  Toast.makeText(MainActivity.this, "数据修改成功", 1000).show();  }  });  /* 删除数据 ; 设置deleteData点击事件监听器 */  deleteData.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 与数据库建立联系,获得SQLiteDatabase的对象 */  SQLiteDatabase sqliteDatabase = helper.getWritableDatabase();  /* 使用sql语句直接进行删除 */  //sqliteDatabase.execSQL("");  /* 调用:SQLiteDatabase对象的delete()的方法删除数据 */  /* 参1:表名; 参2:条件语句; 参3:条件语句中对应占位符的值 */  sqliteDatabase.delete("student", "id=?", new String[]{"1"});  Toast.makeText(MainActivity.this, "数据删除成功", 1000).show();  }  });  /* 查看数据 *//* selectData点击事件监听器 */  selectData.setOnClickListener(new OnClickListener() {  public void onClick(View v) {  /* 获取SQLiteDatabase的对象 */  SQLiteDatabase sqliteDatabase = helper.getReadableDatabase();  /* 调用SQLiteDatabase的query()方法进行查询,返回一个Cursor对象:由数据库查询返回的结果集对象 */  /* 参1 String:表名  * 参2 String[]:需要查询的列;  * 参3 String :查询条件;  * 参4 String[]:查询条件的参数;  * 参5 String: 对查询的结果进行分组;  * 参6 String: 对分组结果进行限制;  * 参7 String: 对查询结果进行排序;  *  * */  Cursor cursor = sqliteDatabase.query("student", new String[]{"id","name"}, "id=?", new String[]{"1"}, null, null, null);  /* 保存结果集中对应字段的数据 */  String id = null;  String name = null;  /* 从结果集中读取数据 */  while(cursor.moveToNext()){  id = cursor.getString(cursor.getColumnIndex("id"));  name = cursor.getString(cursor.getColumnIndex("name"));  }  Toast.makeText(MainActivity.this, "查询数据为:id="+id+" \n name="+name, 1000).show();  }  });  }  }

六、结束语

如果你想要开发 Android 应用程序,一定需要在 Android 上存储数据,使用 SQLite 数据库是一种非常好的选择。


更多相关文章

  1. Android解析Intent Filter的方法
  2. android中访问本机服务器的方法
  3. Android中使用imageviewswitcher 实现图片切换轮播导航的方法
  4. Android NDK环境创建方法简介
  5. Unity3D和Android之间的方法交互(jar模式)

随机推荐

  1. 图片循环滑动
  2. android dialog宽度无法填满屏幕解决方案
  3. android把彩色图像变成灰度图(黑白)
  4. android获取资源文件非主流方法
  5. Android反射机制技术的使用示例
  6. android res目录下存放图片文件夹 i m h
  7. Only the original thread that created
  8. Android读取系统时间
  9. avd安装apk
  10. Android剪贴板学习