在 SQL 数据库中保存数据

上一课 下一课

本课程将向您展示如何

  1. 定义架构和契约
  2. 使用 SQL 辅助工具创建数据库
  3. 将信息输入到数据库
  4. 从数据库读取信息
  5. 从数据库删除信息
  6. 更新数据库

您还应阅读

  • 使用数据库

将数据保存到数据库对于重复或结构化数据(比如契约信息) 而言是理想之选。本课程假定您基本熟悉 SQL 数据库并且可帮助您开始在 Android 中使用 SQLite 数据库。 您在 Android 中使用数据库所需的 API 在android.database.sqlite软件包中提供。

定义架构和契约

SQL 数据库的主要原则之一是架构:数据库如何组织的正式声明。 架构体现于您用于创建数据库的 SQL 语句。您会发现它有助于创建伴随类,即契约类,其以一种系统性、自记录的方式明确指定您的架构布局。

契约类是用于定义 URI、表格和列名称的常数的容器。 契约类允许您跨同一软件包中的所有其他类使用相同的常数。 您可以在一个位置更改列名称并使其在您整个代码中传播。

组织契约类的一种良好方法是将对于您的整个数据库而言是全局性的定义放入类的根级别。 然后为枚举其列的每个表格创建内部类。

注意:通过实现BaseColumns接口,您的内部类可继承调用的主键字段_ID,某些 Android 类(比如光标适配器)将需要内部类拥有该字段。 这并非必需项,但可帮助您的数据库与 Android 框架协调工作。

例如,该代码段定义了单个表格的表格名称和列名称:

public final class FeedReaderContract {  // To prevent someone from accidentally instantiating the contract class,  // give it an empty constructor.  public FeedReaderContract() {}  /* Inner class that defines the table contents */  public static abstract class FeedEntry implements BaseColumns {    public static final String TABLE_NAME = "entry";    public static final String COLUMN_NAME_ENTRY_ID = "entryid";    public static final String COLUMN_NAME_TITLE = "title";    public static final String COLUMN_NAME_SUBTITLE = "subtitle";    ...  }}

使用 SQL 辅助工具创建数据库

在您定义了数据库的外观后,您应实现创建和维护数据库和表格的方法。 这里有一些典型的表格创建和删除语句:

private static final String TEXT_TYPE = " TEXT";private static final String COMMA_SEP = ",";private static final String SQL_CREATE_ENTRIES =  "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +  FeedEntry._ID + " INTEGER PRIMARY KEY," +  FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +  FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +  ... // Any other options for the CREATE command  " )";private static final String SQL_DELETE_ENTRIES =  "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

就像您在设备的内部存储中保存文件那样,Android 将您的数据库保存在私人磁盘空间,即关联的应用。 您的数据是安全的,因为在默认情况下,其他应用无法访问此区域。

SQLiteOpenHelper类中有一组有用的 API。当您使用此类获取对您数据库的引用时,系统将只在需要之时而不是应用启动过程中执行可能长期运行的操作:创建和更新数据库。 您只需调用getWritableDatabase()getReadableDatabase()

注意:由于它们可能长期运行,因此请确保您在后台线程中调用getWritableDatabase()getReadableDatabase(), 比如使用AsyncTaskIntentService

要使用SQLiteOpenHelper,请创建一个 替代onCreate()onUpgrade()onOpen()回调方法的子类。您可能还希望实现onDowngrade(), 但这并非必需操作。

例如,这里有一个使用如上所示一些命令的SQLiteOpenHelper的实现:

public class FeedReaderDbHelper extends SQLiteOpenHelper {  // If you change the database schema, you must increment the database version.  public static final int DATABASE_VERSION = 1;  public static final String DATABASE_NAME = "FeedReader.db";  public FeedReaderDbHelper(Context context) {    super(context, DATABASE_NAME, null, DATABASE_VERSION);  }  public void onCreate(SQLiteDatabase db) {    db.execSQL(SQL_CREATE_ENTRIES);  }  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    // This database is only a cache for online data, so its upgrade policy is    // to simply to discard the data and start over    db.execSQL(SQL_DELETE_ENTRIES);    onCreate(db);  }  public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {    onUpgrade(db, oldVersion, newVersion);  }}

要访问您的数据库,请实例化SQLiteOpenHelper的子类:

FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());

将信息输入到数据库

通过将一个ContentValues对象传递至insert()方法将数据插入数据库:

// Gets the data repository in write modeSQLiteDatabase db = mDbHelper.getWritableDatabase();// Create a new map of values, where column names are the keysContentValues values = new ContentValues();values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);values.put(FeedEntry.COLUMN_NAME_TITLE, title);values.put(FeedEntry.COLUMN_NAME_CONTENT, content);// Insert the new row, returning the primary key value of the new rowlong newRowId;newRowId = db.insert(    FeedEntry.TABLE_NAME,    FeedEntry.COLUMN_NAME_NULLABLE,    values);

insert()的第一个参数即为表格名称。第二个参数指定在ContentValues为空的情况下框架可在其中插入 NULL 的列的名称(如果您将其设置为"null", 那么框架将不会在没有值时插入行。)

从数据库读取信息

要从数据库中读取信息,请使用query()方法,将其传递至选择条件和所需列。该方法结合insert()update()的元素,除非列列表定义了您希望获取的数据,而不是希望插入的数据。 查询的结果将在Cursor对象中返回给您。

SQLiteDatabase db = mDbHelper.getReadableDatabase();// Define a projection that specifies which columns from the database// you will actually use after this query.String[] projection = {  FeedEntry._ID,  FeedEntry.COLUMN_NAME_TITLE,  FeedEntry.COLUMN_NAME_UPDATED,  ...  };// How you want the results sorted in the resulting CursorString sortOrder =  FeedEntry.COLUMN_NAME_UPDATED + " DESC";Cursor c = db.query(  FeedEntry.TABLE_NAME, // The table to query  projection,                // The columns to return  selection,                // The columns for the WHERE clause  selectionArgs,              // The values for the WHERE clause  null,                   // don't group the rows  null,                   // don't filter by row groups  sortOrder                 // The sort order  );

要查看游标中的某一行,请使用Cursor移动方法之一,您必须在开始读取值之前始终调用这些方法。 一般情况下,您应通过调用moveToFirst()开始,其将“读取位置”置于结果中的第一个条目中。 对于每一行,您可以通过调用Cursor获取方法之一读取列的值,比如getString()getLong()。对于每种获取方法,您必须传递所需列的索引位置,您可以通过调用getColumnIndex()getColumnIndexOrThrow()获取。例如:

cursor.moveToFirst();long itemId = cursor.getLong(  cursor.getColumnIndexOrThrow(FeedEntry._ID));

从数据库删除信息

要从表格中删除行,您需要提供识别行的选择条件。 数据库 API 提供了一种机制,用于创建防止 SQL 注入的选择条件。 该机制将选择规范划分为选择子句和选择参数。 该子句定义要查看的列,还允许您合并列测试。 参数是根据捆绑到子句的项进行测试的值。由于结果并未按照与常规 SQL 语句相同的方式进行处理,它不受 SQL 注入的影响。

// Define 'where' part of query.String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";// Specify arguments in placeholder order.String[] selectionArgs = { String.valueOf(rowId) };// Issue SQL statement.db.delete(table_name, selection, selectionArgs);

更新数据库

当您需要修改数据库值的子集时,请使用update()方法。

更新表格可将insert()的内容值句法与delete()where句法相结合。

SQLiteDatabase db = mDbHelper.getReadableDatabase();// New value for one columnContentValues values = new ContentValues();values.put(FeedEntry.COLUMN_NAME_TITLE, title);// Which row to update, based on the IDString selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";String[] selectionArgs = { String.valueOf(rowId) };int count = db.update(  FeedReaderDbHelper.FeedEntry.TABLE_NAME,  values,  selection,  selectionArgs);

更多相关文章

  1. Android使用ViewPager实现图片轮播(高度自适应,左右循环,自动轮播)
  2. 【Android】Java回调原理并结合Android源码进行理解
  3. Android中使用WebView与JS交互全解析
  4. 第二行代码学习笔记——第二章(2)
  5. Android重温--触屏事件
  6. android显示RGB565数据图像
  7. Android(安卓)ProgressBar详解以及自定义
  8. 实现Android监控任意控件或按键双击事件方法
  9. Android工程中R类访问不到工程中的资源文件的解决方法

随机推荐

  1. Android无EditText时获取扫描设备的扫描
  2. 【链接】android图片压缩总结
  3. Android触摸事件小小画板(7)
  4. Android(安卓)之 对话框总结
  5. Android(安卓)SDK开发环境Eclipse安装搭
  6. android 获取手机图片裁剪后分享 2
  7. 总结:Android(安卓)JNI开发疑点
  8. [Android] ICS | JB 锁屏农历的添加
  9. android java js 回调 真心好用
  10. 第四章-View的工作原理(MeasureSpec、Lay