您的位置:首页 > 数据库

1.5.3 在SQL数据库中存储数据

2016-06-21 19:04 621 查看

Saving Data in SQL Databases

Previous

Next

This lesson teaches you to

本节涉及:

定义schema和contract
使用SQL helper 创建数据库
将信息放入数据库
从数据库中读取数据
从数据库中删除数据
升级数据库

You should also read

拓展阅读

Using Databases

Saving data to a database is ideal for repeating or structured data,such as contact information. This class assumes that you arefamiliar with SQL databases in general and helps you get started withSQLite databases on Android. The APIs you'll need to use
a databaseon Android are available in the
android.database.sqlite
package.

重复的、结构性的数据(比如联系人信息包含姓名、号码等),尤其适用于存储到数据库中。本节课假定你对于SQL数据库整体上已经比较熟悉,并将帮助你开始在Android上使用SQLite数据库。使用数据库需要用到的api可在
android.database.sqlite
包中得到。


Define a Schema and Contract定义Schema和Contract

One of the main principles of SQL databases is the schema: a formaldeclaration of how the database is organized. The schema is reflected in the SQLstatements that you use to create your database. You may find it helpful tocreate a companion class, known
as a contract class, which explicitly specifiesthe layout of your schema in a systematic and self-documenting way.

Schema是SQL数据库中几个比较重要的概念之一:它是对于数据库的结构的正式地声明。在创建数据库的SQL声明中可以反映出schema。创建一个伴生类(companion class)也就是契约类(contract class)能够显式地以系统地、自解释的方式指定schema的布局。

A contract class is a container for constants that define names for URIs,tables, and columns. The contract class allows you to use the same constantsacross all the other classes in the same package. This lets you change a columnname in one place and have
it propagate throughout your code.

一个契约类可以被视为对于定义URI、表、列等常量的容器。契约类的创建可以让你在一个包中的所有类里使用相同的常量。

A good way to organize a contract class is to put definitions that areglobal to your whole database in the root level of the class. Then create an innerclass for each table that enumerates its columns.

通常将全局变量的定义放在契约类的根层次,然后为每一个表创建一个内部类(将表中的列枚举出来)。

Note: By implementing the
BaseColumns
interface, your inner class can inherit a primarykey field called
_ID
that some Android classes such as cursor adaptorswill expect it to have. It's not required, but this can help your databasework harmoniously with the Android framework.
注意:通过实现
BaseColumns接口,内部类可以继承一个叫做“_ID”的主键值,对某些类比如cursor adaptors非常适用。当然这不是必须的,但这样做可以让你的数据库更好地配合android框架层的工作。

For example, this snippet defines the table name and column names for asingle table:

举例:以下代码片段为一个表定义了表名和列名。

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";
        ...
    }
}

Create a Database Using a SQL Helper使用SQL helper创建一个数据库

Once you have defined how your database looks, you should implement methodsthat create and maintain the database and tables. Here are some typicalstatements that create and delete a table:

一旦定义了数据库的“外观”,就应该实现用于创造和维护数据库的方法。以下是一些典型的用于创建和删除一张表的声明语句。

private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private<
10ff7
span class="pln"> 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;

Just like files that you save on the device's
internalstorage, Android stores your database in private disk space that's associatedapplication. Your data is secure, because by default this area is notaccessible to other applications.

就像是存储在设备内置存储的文件一样,android也将与应用相关的数据库存储在了私人空间。因为默认的设置下,该空间对于其他应用是不可及的,故而数据是安全的。

A useful set of APIs is available in the
SQLiteOpenHelper
class. When you use this class to obtain references to your database,
the systemperforms the potentially long-running operations of creating and updating the database only whenneeded and
not during app startup. All you need to do is call
getWritableDatabase()
or
getReadableDatabase()
.

SQLiteOpenHelper类中包含一系列有用的api。使用该类获得数据库的引用时,系统只会在需要的时候执行长期的创建和升级数据库的操作,而不会在应用开启时就执行。


Note: Because they can be long-running,be sure that you call
getWritableDatabase()
or
getReadableDatabase()
in a background thread,such as with
AsyncTask
or
IntentService
.
注意:因为这些操作是耗时的,一定在后台线程调用
getWritableDatabase()
or
getReadableDatabase()
调用这两个方法。

To use
SQLiteOpenHelper
, create a subclass thatoverrides the
onCreate()
,
onUpgrade()
and
onOpen()
callback methods. You may alsowant to implement
onDowngrade()
,but it's not required.

创建
SQLiteOpenHelper
red的子类以重写
onCreate()
,
onUpgrade()
and
onOpen()
等回调方法,而
onDowngrade()
而方法一般没有必要重写。

For example, here's an implementation of
SQLiteOpenHelper
that uses some of the commands shown above:

以下是示例。

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);
    }
}

To access your database, instantiate your subclass of
SQLiteOpenHelper
:

实例化
SQLiteOpenHelper
:S的子类以操作数据库。

FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());


Put Information into a Database

向数据库中放入信息。

Insert data into the database by passing a
ContentValues
object to the
insert()
method:

通过 传递一个
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_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 row
long newRowId;
newRowId = db.insert(
         FeedEntry.TABLE_NAME,
         FeedEntry.COLUMN_NAME_NULLABLE,
         values);

The first argument for
insert()
is simply the
table name. The second argument providesthe name of a column in which the framework can insert NULL in the event that the
ContentValues
is
empty (if you instead set this to
"null"
,then the framework will not insert a row when there are no values).

ins
insert()
ert方法的第一个参数是表名,第二个参数提供了列名(当ContentValues值为空时可以插入NULL,当该参数被设置为null时则不会插入)

Read Information from a Database从数据库中读取信息

To read from a database, use the
query()
method,
passing it your selection criteria and desired columns.The method combines elements of
insert()
and
update()
, except the column
listdefines the data you want to fetch, rather than the data to insert. The results of the queryare returned to you in a
Cursor
object.

使用
query()
m方法,传入你的选择规则个期望的列以从数据库中读取信息。该方法汇合了
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 Cursor
String 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
    );

To look at a row in the cursor, use one of the
Cursor
movemethods, which you must always call before you begin reading values. Generally, you
should startby calling
moveToFirst()
, which places the "read position" on thefirst entry in the results. For each row, you can
read a column's value by calling one of the
Cursor
get methods, such as
getString()
or
getLong()
. For each of the get methods,you must pass the index position of the column you desire, which you can get by calling
getColumnIndex()

or
getColumnIndexOrThrow()
.For example:

为了查看cursor中的某一行,在你开始读取值之前必须一直调用
Cursor
类中移动游标的方法。通常,开始的时候调用
moveToFirst()
方法,会将读取位置放置在结果中的第一个入口。对于每一行,调用
getString()
or
getLong()
等获取数据的方法以读取某一个列的值。对于每一个获取数据的方法(get开头),必须传递你所期望的列的索引位置,通常使用
getColumnIndex()
or
getColumnIndexOrThrow()
.方法。

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

Delete Information from a Database从数据库中删除数据

To delete rows from a table, you need to provide selection criteria thatidentify the rows. The database API provides a mechanism for creating selectioncriteria that protects against SQL injection. The mechanism divides theselection specification into a selection
clause and selection arguments. Theclause defines the columns to look at, and also allows you to combine columntests. The arguments are values to test against that are bound into the clause.Because the result isn't handled the same as a regular SQL statement,
it isimmune to SQL injection.

为了从表中删除某几行,需要提供指定行的选择规则。数据库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 a Database

更新数据库

When you need to modify a subset of your database values, use the
update()

method.

当需要修饰数据库中值得子集时,使用
update()
方法。

Updating the table combines the content values syntax of
insert()

with the
where
syntaxof
delete()
.

更新一张表包含了
insert()
方法中content values的句法和
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 ID
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };

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


Next class
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: