1.5.3 在SQL数据库中存储数据
2016-06-21 19:04
621 查看
Saving Data in SQL Databases
PreviousNext
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.sqlitepackage.
重复的、结构性的数据(比如联系人信息包含姓名、号码等),尤其适用于存储到数据库中。本节课假定你对于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, knownas 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
BaseColumnsinterface, your inner class can inherit a primarykey field called
_IDthat 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
SQLiteOpenHelperclass. 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
AsyncTaskor
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.
创建
SQLiteOpenHelperred的子类以重写
onCreate(),
onUpgrade()and
onOpen()等回调方法,而
onDowngrade()而方法一般没有必要重写。
For example, here's an implementation of
SQLiteOpenHelperthat 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
ContentValuesobject 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
ContentValuesis
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 thequery()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
Cursorobject.
使用
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
Cursormovemethods, 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
Cursorget 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 selectionclause 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 theupdate()
method.
当需要修饰数据库中值得子集时,使用
update()方法。
Updating the table combines the content values syntax of
insert()
with the
wheresyntaxof
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
相关文章推荐
- 编译C连接MySQL 提示 error while loading shared libraries: libmysqlclient.so.
- 初学Redis(四)简单实现Redis缓存中的排序功能
- 按周,按月,按日,按小时分组统计数据
- 初学Redis(三)用Redis作为MySQL数据库的缓存
- 初学Redis(二)用Redis作为MySQL数据库的缓存
- mysql select for update
- 初学Redis(一)认识Redis
- mysql
- PHP中 memcache 基本的增删改查
- 数据库批量到处的工具 SQLyog
- MySQL字符串函数
- sql 图 ,树,层次
- oracle latch:row cache object,latch free案例处理
- mysql中的数据类型enum和set
- 2016/6/21--网页点击保存按钮将数据存到数据库
- oracle索引使用监控
- CentOS 6.5 搭建PHP环境(Nginx+MariaDB+PHP7)
- SQL Server2005连接Oracle 11g详细步骤
- MySQL问题集锦
- MySQL问题集锦