在 SQL 数据库中保存数据

使用数据库

将数据保存到数据库对于重复或结构化数据(比如契约信息)而言是理想之选。 本课程假定您基本熟悉 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,
    // make the constructor private.
    private FeedReaderContract() {}

    /* Inner class that defines the table contents */
    public static class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "entry";
        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_TITLE + TEXT_TYPE + COMMA_SEP +
    FeedEntry.COLUMN_NAME_SUBTITLE + TEXT_TYPE + " )";

private static final String SQL_DELETE_ENTRIES =
    "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

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

SQLiteOpenHelper

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

注:

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

要使用 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 mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();

// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);

// Insert the new row, returning the primary key value of the new row
long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);

insert() 的第一个参数即为表格名称。

第二个参数将指示框架在 ContentValues 为空(即,您没有 put 任何值)时执行哪些操作。如果指定列名称,则框架将插入一行并将该列的值设置为 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_SUBTITLE
    };

// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };

// How you want the results sorted in the resulting Cursor
String sortOrder =
    FeedEntry.COLUMN_NAME_SUBTITLE + " 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_TITLE + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { "MyTitle" };
// Issue SQL statement.
db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);

更新数据库

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

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

SQLiteDatabase db = mDbHelper.getReadableDatabase();

// New value for one column
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);

// Which row to update, based on the title
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };

int count = db.update(
    FeedReaderDbHelper.FeedEntry.TABLE_NAME,
    values,
    selection,
    selectionArgs);

我的微信二维码如下,欢迎交流讨论

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧

微信订阅号二维码如下:

Android 的 Sqlite基本操作的更多相关文章

  1. Android的SQLite基本操作

    涉及SQLite的增删改查,结果用log显示 ? 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 ...

  2. android 一个SQLite数据库多个数据表的基本使用框架 (带demo)

    android 一个SQLite数据库多个数据表(带demo) 前言        demo演示        一.搭建        二.建立实体类        三.建立数据库操作类        ...

  3. Android之SQLite数据存储

    一.SQLite保存数据介绍 将数据库保存在数据库对于重复或者结构化数据(比如契约信息)而言是理想之选.SQL数据库的主要原则之一是架构:数据库如何组织正式声明.架构体现于用于创建数据库的SQL语句. ...

  4. android安卓Sqlite数据库实现用户登录注册

    看了很多别人写的安卓SQlite数据的操作代码,一点也不通俗易懂,我觉得我写的不错,而且安卓项目也用上了,所以在博客园里保存分享一下!建立一个类 并继承SQLiteOpenHelper public ...

  5. Android中SQLite数据库小计

    2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...

  6. android 对sqlite数据库的增删改查等各种操作

    转载:http://blog.csdn.net/vrix/article/details/6717090 package com.sqlite.main; import java.io.File; i ...

  7. Android学习---SQLite数据库的增删改查和事务(transaction)调用

    上一篇文章中介绍了手工拼写sql语句进行数据库的CRUD操作,本文将介绍调用sqlite内置的方法实现CRUD操作,其实质也是通过拼写sql语句. 首先,创建一个新的android项目: 其次,查看代 ...

  8. android数据库SQLite的设计模式

    Dao设计模式可能是使用最多的数据库的设计模式其基本思路是将数据库操作的代码 与设计代码分离以便于维护和升级.具体的实现方法是使用包,然后在设计代码中调 用数据库的操作代码,dao设计模式需要创建5个 ...

  9. Android使用SQLite数据库(2)

    打开SQLite数据库,首先要建立一个DatabaseHelper类的实例,然后,再获得数据库: DatabaseHelper mDBH; SQLiteDatabase db; mDBH = new ...

随机推荐

  1. 线性结构与树形结构相互转换(ES6实现)

    前言 当树形结构的层级越来越深时,操作某一节点会变得越来越费劲,维护成本不断增加.所以线性结构与树形的相互转换变得异常重要! 首先,我们约定树形结构如下: node = { id: number, / ...

  2. [CEOI 2004]Sweet

    Description 题面链接 有 \(n\) 种糖果.第 \(i\) 种糖果有 \(m_i\) 个.取出一些糖果,至少 \(a\) 个,但不超过 \(b\) 个.求方案数. \(1\leq n\l ...

  3. [COGS 2258][HZOI 2015]复仇的序幕曲

    Description 你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言 当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深 他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平 ...

  4. [Wc2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

  5. linux x86内核中的分页机制

    Linux采用了通用的四级分页机制,所谓通用就是指Linux使用这种分页机制管理所有架构的分页模型,即便某些架构并不支持四级分页.对于常见的x86架构,如果系统是32位,二级分页模型就可满足系统需求: ...

  6. php中sql语句常见错误

    .php文件中sql语句的写法导致的错误如下: 1.$logSql="select * from jd_login where uname=".$u."and upwd= ...

  7. C语言程序设计第二次作业——顺序结构

    (一)改错题 1.输出带框文字:在屏幕上输出以下3行信息. 错误信息1: 错误原因:i和d位置错误 改正方法:i和d位置互换 错误信息2: 错误原因:\n后缺了一个" 改正方法:\n后加一个 ...

  8. TCP/IP学习笔记__mbuf

    Socket发送和接收数据都是写入和读取mbuf(存储器缓存)来完成的.下面着重介绍下Sendto函数与mbuf的关系: 以UDP协议为例: 1.UDP的输出执行过程: UDP的输出执行过程 2.协议 ...

  9. 关于一些基础的Java问题的解答(二)

    6. Hashcode的作用 官方对于hashCode的解释如下: Whenever it is invoked on the same object more than once during an ...

  10. Win10 下Cmake编译配置 Opencv3.1 + Cuda7.5 + VS2013

    折腾了三天终于配置成功了,在此写下编译配置的全部步骤和遇到的很多坑. 整体介绍: OpenCV 中 CUDA 实现的函数还不是太多,使用前要在OpenCV的官网上确认以下你想要的功能是否已经实现,否则 ...