Android 数据库

获得了SQLiteDatabase对象以后,我们就可以通过调用SQLiteDatabase的实例方法来对数据库进行操作了。SQLiteDatabase除了提供像execSQL()和rawQuery()这种直接对SQL语句解析的方法外,还针对INSERT、UPDATE、DELETE和SELECT等操作专门定义了相关的方法。下面是对常用的数据库操作方法的总结。

public void execSQL (String sql),public void execSQL (String sql, Object[]bindArgs),执行一条非查询SQL语句,执行期间会获得该SQLite数据库的写锁,执行完毕后锁释放。不支持用;隔开的多条SQL语句。若SQL语句执行失败会抛出SQLException异常。

参数:sql,需要执行的SQL语句字符串。

bindArgs,SQL语句中表达式的?占位参数列表,仅仅支持String、byte数组、long和double型数据作为参数。

返回值:无。

public Cursor rawQuery (String sql, String[] args),public Cursor rawQuery-WithFactory(SQLiteDatabase.CursorFactory factory, String sql, String[]args, String editTable),执行一条SQL查询语句,并把查询结果以Cursor的子类对象的形式返回。

参数:sql,需要执行的SQL语句字符串。

args,SQL语句中表达式的?占位参数列表,参数只能为String类型。

factory,CursorFactory对象,用来构造查询完毕时返回的Cursor的子类对象,为null时使用默认的CursorFactory构造。

editable,第一个可编辑的表名。

返回值:指向第一行数据之前的Cursor子类对象。

public long insert (String table, String nullColumnHack, ContentValuesinitialValues),public long insertOrThrow (String table, String nullColumnHack,

ContentValues initialValues),向指定表中插入一行数据。

参数:table,需要插入数据的表名。

nullColumnHack,这个参数需要传入一个列名。SQL标准并不允许插入所有列均为空的一行数据,所以当传入的initialValues值为空或者为0时,用nullColumnHack参数指定的列会被插入值为NULL的数据,然后再将此行插入到表中。

initalValues,用来描述要插入行数据的ContentValues对象,即列名和列值的映射。

返回值:新插入行的行id。如果有错误发生返回-1。

public int update (String table, ContentValues values, String whereClause,String[] whereArgs),更新表中指定行的数据。

参数:table,更新数据的表名。

values,用来描述更新后的行数据的ContentValues对象,即列名和列值的映射。whereClause,可选的where语句(不包括WHERE关键字),用来指定需要更新的行。若传入null则表中所有的行均会被更新。

whereArgs,where语句中表达式的?占位参数列表,参数只能为String类型。返回值:被更新的行的数量。

public int delete (String table, String whereClause, String[] whereArgs),删除表中指定的行。

参数:table,需要删除行的表名。

whereClause,可选的where语句(不包括WHERE关键字),用来指定需要删除的行。

若传入null则会删除所有的行。

whereArgs,where语句中表达式的?占位参数列表,参数只能为String类型。

返回值:若传入了正确的where语句则被删除的行数会被返回。若传入null,则会返回0。若要删除所有行并且返回删除的行数,则需要在where语句的地方传入字符串1。

public Cursor query (String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having, String orderBy,String limit)public Cursor query (boolean distinct, String table, String[] columns,String selection, String[] selectionArgs, String groupBy, String having,String orderBy, String limit)public Cursor query (String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having, String orderBy)public Cursor queryWithFactory (SQLiteDatabase.CursorFactory cursorFactory,boolean distinct, String table, String[] columns, String selection, String[]selectionArgs, String groupBy, String having, String orderBy, String limit)

根据检索条件检索指定表并把满足条件的行以Cursor的子类对象返回。参数:table,检索的表名。

columns,由需要返回列的列名所组成的字符串数组,传入null会返回所有的列。selection,指定需要返回的行的where语句(不包括WHERE关键字)。传入null则返回所有行。

selectionArgs,where语句中表达式的?占位参数列表,参数只能为String类型。

groupBy,对结果集进行分组的group by语句(不包括GROUP BY关键字)。传入null将不对结果集进行分组。

having,对分组结果集设置条件的having语句(不包括HAVING关键字)。必须配合groupBy参数使用,传入null将不对分组结果集设置条件。

orderBy,对结果集进行排序的order by语句(不包括ORDER BY关键字)。传入null将对结果集使用默认的排序。

limit,对返回的行数进行限制的limit语句(不包括LIMIT关键字)。传入null将不限制返回的行数。

distinct,如果希望结果集没有重复的行传入true,否则传入false。

cursorFactory,使用这个CursorFactory来构造返回的Cursor子类对象,传入null使用默认的CursorFactory。

返回值:指向第一行数据之前的Cursor子类对象。

了解了这些函数,下面让我们来把数据库的操作填充到之前的MyHelper骨架中,并且在程序中利用MyHelper创建并打开数据库名为code.db的数据库,最后向数据库中的countrycode表插入数据,如表9-1所示。

表9-1 countrycode表中包含的数据

 

首先新建项目SQLite2,把之前MyHelper的骨架复制到MyHelper.java,在MyHelper类中为表名和列名定义字符串静态常量。

TB_NAME指定了表名,而ID、COUNTRY和CODE则分别指定了各个列的列名。

然后在onCreate()和onUpgrade()方法中加入创建表和删除表的操作。

  
  
  
  
  1. @Override  
  2. public void onCreate(SQLiteDatabase db) {  
  3. // 创建表countrycode  
  4. db.execSQL("CREATE TABLE IF NOT EXISTS "  
  5. + TB_NAME + " ("  
  6. + ID + " INTEGER PRIMARY KEY,"  
  7. + COUNTRY + " VARCHAR,"  
  8. + CODE + " INTEGER)");  

调用了execSQL()方法来创建如表9-1所示的表。

  
  
  
  
  1. @Override  
  2. public void onUpgrade(SQLiteDatabase db,  
  3. int oldVersion, int newVersion) {  
  4. //删除以前的旧表,创建一张新的空表  
  5. db.execSQL("DROP TABLE IF EXISTS "+TB_NAME);  
  6. onCreate(db);  

每次需要更新数据库版本时,将以前的表删除,重新创建空表。这是很极端的一种做法,会删除以前数据库内的所有数据。其实在对数据库进行改变时,若需要保留之前数据库中的数据,可以使用ALERT TABLE语句来直接修改表。

接下来就是在Activity中程序的运行部分了,编辑SQLite2.java,代码如下所示。

  
  
  
  
  1. 1 package com.studio.android.chp9.ex3;  
  2. 2  
  3. 3 import android.app.Activity;  
  4. 4 import android.content.ContentValues;  
  5. 5 import android.database.sqlite.SQLiteDatabase;  
  6. 6 import android.os.Bundle;  
  7. 7  
  8. 8 public class SQLite2 extends Activity {  
  9. 9  
  10. 10 public static final String DB_NAME = "code.db";  
  11. 11 public static final int VERSION = 1;  
  12. 12  
  13. 13 MyHelper helper;  
  14. 14 SQLiteDatabase db;  
  15. 15  
  16. 16 /** Activity第一次创建时调用 */  
  17. 17 @Override  
  18. 18 public void onCreate(Bundle savedInstanceState) {  
  19. 19 super.onCreate(savedInstanceState);  
  20. 20 setContentView(R.layout.main);  
  21. 21  
  22. 22 //初始化数据库辅助对象  
  23. 23 helper = new MyHelper(this, DB_NAME, null, VERSION);  
  24. 24  
  25. 25 //获得可读写的SQLiteDatabase对象  
  26. 26 db = helper.getWritableDatabase();  
  27. 27  
  28. 28 //用insert方法像数据库中插入"中国 86"  
  29. 29 ContentValues values = new ContentValues();  
  30. 30 values.put(MyHelper.COUNTRY, "中国");  
  31. 31 values.put(MyHelper.CODE, 86);  
  32. 32 db.insert(MyHelper.TB_NAME, MyHelper.ID, values);  
  33. 33  
  34. 34 //使用insert方法  
  35. 35 //插入完全为空的ContentValues,  
  36. 36 //再使用update方法修改行数据为"意大利 39"  
  37. 37 db.insert(MyHelper.TB_NAME, MyHelper.ID,null);  
  38. 38 values.clear();  
  39. 39 values.put(MyHelper.COUNTRY, "意大利");  
  40. 40 values.put(MyHelper.CODE, 39);  
  41. 41 db.update(MyHelper.TB_NAME, values, MyHelper.ID + " = 2",null);  
  42. 42  
  43. 43 //使用execSQL方法插入数据"洪都拉斯 504"  
  44. 44 db.execSQL("INSERT INTO "  
  45. 45 + MyHelper.TB_NAME + "("  
  46. 46 + MyHelper.COUNTRY + ","  
  47. 47 + MyHelper.CODE + ") VALUES "  
  48. 48 + "('洪都拉斯',504)");  
  49. 49 }  
  50. 50  
  51. 51 @Override  
  52. 52 public void onDestroy() {  
  53. 53 //程序退出时删除所有行  
  54. 54 db.delete(MyHelper.TB_NAME,null,null);  
  55. 55 super.onDestroy();  
  56. 56 }  
  57. 57 } 

首先在为数据库名和版本分别定义两个静态常量。

  
  
  
  
  1. 10 public final String DB_NAME = "code.db";  
  2. 11 public final int VERSION = 1

DB_NAME指定了要创建/打开的数据库的名字,VERSION则指定了数据库的版本。

这里为了演示方法的使用,在Activity的onCreate()方法中分别用了三种不同的方式来向数据库中插入、更新数据。在实际的应用程序编写过程中请读者根据情况,自行选择操作数据库的方式。首先是构造一个ContentValues的对象,然后用insert方法将数据插入到数据库。

  
  
  
  
  1. 28 //用insert方法向数据库中插入"中国 86"  
  2. 29 ContentValues values = new ContentValues();  
  3. 30 values.put(MyHelper.COUNTRY, "中国");  
  4. 31 values.put(MyHelper.CODE, 86);  
  5. 32 db.insert(MyHelper.TB_NAME, MyHelper.ID, values); 

细心的读者可能会注意到,这里我们并没有指定_id列的值。这是因为SQLite数据库中将所有声明为“INTEGER PRIMARY KEY”的列自动识别成自增列。在插入一行数据的时候,若不指定自增列的数据或给自增列传入NULL值时,会自动给自增列赋一个所有行中此列里的最大值加1的数。若添加的是第一行则从数字1开始。而这里的_id就是一个自增列,所以在插入这行数据后,此行数据_id列的值为1。

而第二种方式是,先用insert方法插入一个为null的ContentValues,然后再用update方法修改刚才所插入的行。

  
  
  
  
  1. 34 //使用insert方法  
  2. 35 //插入完全为空的ContentValues,  
  3. 36 //再使用update方法修改行数据为"意大利 39"  
  4. 37 db.insert(MyHelper.TB_NAME, MyHelper.ID,null);  
  5. 38 values.clear();  
  6. 39 values.put(MyHelper.COUNTRY, "意大利");  
  7. 40 values.put(MyHelper.CODE, 39);  
  8. 41 db.update(MyHelper.TB_NAME, values, MyHelper.ID + " = 2",null); 

由于传入的ContentValues对象为null,所以将会把由第二个参数设置的列赋值为NULL。这里需要分清NULL列和空列:空列是没有任何值的列,而NULL列的意思是值为NULL的列。这里我们第二个参数设置的是_id列,又由于_id列是自增列,传入NULL会自增赋值,所以最终_id列的值为2。然后再使用update方法,更新_id为2的行,把国家信息和区号信息填入。

  
  
  
  
  1. 43 //使用execSQL方法插入数据"洪都拉斯 504"  
  2. 44 db.execSQL("INSERT INTO "  
  3. 45 + MyHelper.TB_NAME + "("  
  4. 46 + MyHelper.COUNTRY + ","  
  5. 47 + MyHelper.CODE + ") VALUES "  
  6. 48 + "('洪都拉斯',504)"); 

最后使用的是直接执行SQL语句字符串的方式插入行。

程序退出时清空表中数据,避免下次启动程序时重复添加数据。

  
  
  
  
  1. 51 @Override  
  2. 52 public void onDestroy() {  
  3. 53 //程序退出时删除所有行  
  4. 54 db.delete(MyHelper.TB_NAME,null,null);  
  5. 55 super.onDestroy();  
  6. 56 } 

  
  
  
  
  1. public static final String TB_NAME = "countrycode";  
  2. public static final String ID = "_id";  
  3. public static final String COUNTRY = "country";  
  4. public static final String CODE = "code"

你可能感兴趣的:(Android 数据库)