SQL數據庫的主要原則是模式(schema): 一種數據庫被如何組織的正式聲明. 模式被反映在你用來建立你的數據庫的SQL語句中. 你可能會發現建立一個同伴類頗有用,它被稱做(contract)協議類, 它用一種系統和自文檔化的方式明確指定了你的模式的佈局. html
協議類是定義的URI、表格和列名稱常量的容器. 協議類讓你能夠在同一個包的全部其它類那裏使用相同的常量. 這讓你能夠在一個地方對列名稱的改變傳播到你全部的代碼. java
組織一個協議類最好的方式是將對你的整個數據庫全局可用的定義放置到類的根一級別 . 而後爲每個表建立一個內部類,並枚舉出它們的列. android
注意: 經過實現 BaseColumns 接口, 你的內部類能夠繼承到一個稱做 _ID 的主鍵域,一些諸如遊標適配器的Android類將但願有這個東西 . 它也不是必定要有的,但它有助於你的數據庫同Android框架更加的協調 . sql
例如,這個小代碼塊爲一個表定義了表名和列名 : 數據庫
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"; ... } }
一旦你定義好了數據庫是什麼樣子,你就會要實現建立和維護數據庫及其數據表的方法 . 下面是一些建立和刪除一個表格的典型語句 : app
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(). ide
注意: 覺得它們能夠是耗時較長的,請確保你是在一個後臺線程中調用的 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_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);
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 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 );
要在遊標對象中瀏覽一行數據,就使用 Cursor 中的某一個移動方法 , 它們老是必須在你開始讀取值時被調用. 通常而言,一開始你應該調用 moveToFirst(), 它會將「讀取位置」放在結果的第一條的位置 . 對於每一行,你能夠經過調用 Cursor 中的摸一個獲取方法來讀取一列的值 , 好比 getString() 或者 getLong(). 對於每個獲取方法,你必須傳入你想要獲取的列的索引位置 , 它能夠經過調用 getColumnIndex() 或者 getColumnIndexOrThrow() 獲取到. 例如:
cursor.moveToFirst(); long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedEntry._ID) );
要從數據庫中刪除行,你須要提供識別這些行的選擇條件. 數據庫API提供了建立可以防止數據庫注入的選擇條件的機制. 該機制將選擇指標分紅選擇語句和選擇參數 . 語句部分定義了要查找的列,同時也容許你結合列測試 . 參數部分是綁定到語句中的測試用的值 . 由於結果不是處理同一個常規的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() 內含的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);
來源:
http://developer.android.com/training/basics/data-storage/databases.html