当前位置:Gxlcms > 数据库问题 > 数据存储(2)使用SQL数据库

数据存储(2)使用SQL数据库

时间:2021-07-01 10:21:17 帮助过:4人阅读

) 一个组织Contract类的好方式是放置全局数据库的定义在这个类的根层。然后为每一个表创建一个内部类,枚举他们的列。 sunshine的这个WeatherContract类,定义了全局的URI路径:
// The "Content authority" is a name for the entire content provider, similar to the
// relationship between a domain name and its website.  A convenient string to use for the
// content authority is the package name for the app, which is guaranteed to be unique on the
// device.
public static final String CONTENT_AUTHORITY = "com.loveqiqi.sy.mysunshine";

// Use CONTENT_AUTHORITY to create the base of all URI‘s which apps will use to contact
// the content provider.
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

// Possible paths (appended to base content URI for possible URI‘s)
// For instance, content://com.example.android.sunshine.app/weather/ is a valid path for
// looking at weather data. content://com.example.android.sunshine.app/givemeroot/ will fail,
// as the ContentProvider hasn‘t been given any information on what to do with "givemeroot".
// At least, let‘s hope not.  Don‘t be that dev, reader.  Don‘t be that dev.
public static final String PATH_WEATHER = "weather";
public static final String PATH_LOCATION = "location";

每个表有一个静态内部类: 这个内部类一般实现BaseColumns,这样就会有一个primary key, _ID. 这个类列举了表列的名词,然后提供了一些内容提供器需要的Uri。
/*
    Inner class that defines the table contents of the location table
    Students: This is where you will add the strings.  (Similar to what has been
    done for WeatherEntry)
 */
public static final class LocationEntry implements BaseColumns {
    public static final String TABLE_NAME = "location";

    public static final  String COLUMN_LOCATION_SETTING = "location_setting";
    public static final  String COLUMN_COORD_LAT = "coord_lat";
    public static final  String COLUMN_COORD_LONG = "coord_long";
    public static final  String COLUMN_CITY_NAME="city_name";

    public static final Uri CONTENT_URI =
            BASE_CONTENT_URI.buildUpon().appendPath(PATH_LOCATION).build();

    public static final String CONTENT_TYPE =
            ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_LOCATION;
    public static final String CONTENT_ITEM_TYPE =
            ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_LOCATION;

    public static Uri buildLocationUri(long id) {
        return ContentUris.withAppendedId(CONTENT_URI, id);
    }

}

Create a Database Using a SQL Helper


一旦我们定义了我们数据库的样子,应该实现方法,这些方法创建和维护数据库和表格。 这就要实现SQLiteOpenHelper了。 下面是例子:实现onCreate方法创建表。
/**
 * Manages a local database for weather data.
 */
public class WeatherDbHelper extends SQLiteOpenHelper {

    // If you change the database schema, you must increment the database version.
    private static final int DATABASE_VERSION = 2;

    static final String DATABASE_NAME = "weather.db";

    public WeatherDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        final String SQL_CREATE_WEATHER_TABLE = "CREATE TABLE " + WeatherEntry.TABLE_NAME + " (" +
                // Why AutoIncrement here, and not above?
                // Unique keys will be auto-generated in either case.  But for weather
                // forecasting, it‘s reasonable to assume the user will want information
                // for a certain date and all dates *following*, so the forecast data
                // should be sorted accordingly.
                WeatherEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +

                // the ID of the location entry associated with this weather data
                WeatherEntry.COLUMN_LOC_KEY + " INTEGER NOT NULL, " +
                WeatherEntry.COLUMN_DATE + " INTEGER NOT NULL, " +
                WeatherEntry.COLUMN_SHORT_DESC + " TEXT NOT NULL, " +
                WeatherEntry.COLUMN_WEATHER_ID + " INTEGER NOT NULL," +

                WeatherEntry.COLUMN_MIN_TEMP + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_MAX_TEMP + " REAL NOT NULL, " +

                WeatherEntry.COLUMN_HUMIDITY + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_PRESSURE + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_WIND_SPEED + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_DEGREES + " REAL NOT NULL, " +

                // Set up the location column as a foreign key to location table.
                " FOREIGN KEY (" + WeatherEntry.COLUMN_LOC_KEY + ") REFERENCES " +
                LocationEntry.TABLE_NAME + " (" + LocationEntry._ID + "), " +

                // To assure the application have just one weather entry per day
                // per location, it‘s created a UNIQUE constraint with REPLACE strategy
                " UNIQUE (" + WeatherEntry.COLUMN_DATE + ", " +
                WeatherEntry.COLUMN_LOC_KEY + ") ON CONFLICT REPLACE);";
        final  String SQL_CREATE_LOACTION_TABLE = "CREATE TABLE " + LocationEntry.TABLE_NAME + "(" +
                LocationEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                LocationEntry.COLUMN_LOCATION_SETTING + " TEXT UNIQUE NOT NULL," +
                LocationEntry.COLUMN_COORD_LAT + " REAL NOT NULL,"+
                LocationEntry.COLUMN_COORD_LONG + " REAL NOT NULL," +
                LocationEntry.COLUMN_CITY_NAME + " TEXT NOT NULL); ";


        sqLiteDatabase.execSQL(SQL_CREATE_WEATHER_TABLE);
        sqLiteDatabase.execSQL(SQL_CREATE_LOACTION_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, 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
        // Note that this only fires if you change the version number for your database.
        // It does NOT depend on the version number for your application.
        // If you want to update the schema without wiping data, commenting out the next 2 lines
        // should be your top priority before modifying this method.
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + LocationEntry.TABLE_NAME);
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + WeatherEntry.TABLE_NAME);
        onCreate(sqLiteDatabase);
    }
}


这样我们要访问数据库,使用这个类获得数据库的引用。系统执行潜在的长时间运行的创建更新数据库操作仅仅在需要的时候,不会再 应用启动。我们只要调用getWritableDatabase或者getReadableDatabase,因为可能长时间运行,所以要在后台进程调用,比如AsyncTask 或者IntentService(sunshine一直到SyncAdapter)。

public SQLiteDatabase getWritableDatabase ()说明

上面讨论系统在需要的时候去执行这些潜在的长时间运行的操作,在getWritableDatabase方法第一次调用的时候,数据库会打开, 然后onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int) and/oronOpen(SQLiteDatabase) will be called.所以, 数据库的创建是在我们第一次调用这个函数的时候。数据库才被创建。
使用数据库的时候,直接这样: 然后sunshine的在ContentProvider的类的OnCreate中初始化定义的mOpenHelper。我们也只要这么使用就好。
mOpenHelper = new WeatherDbHelper(getContext());
然后就是对数据库的增删改查了。

数据库插入

使用ContentValues
// 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);
第一个参数是表名,第二个参数是设置哪些列可以为空,如果设置为null,那么系统不会插入一个空行),一般是null吧,这样在定义 数据库的时候就需要知道哪些列是可为空的?如果要设置第二个参数的话.

数据库查询


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


public Cursor query (String table,String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

查询的第一个参数:表名 第二个:返回列,string数组,传递null,返回所有列,不推荐,阻止返回冗余数据 第三:哪些行返回,null返回所有行,会格式化为where语句 第四:如果在第三个参数包含?,这里需要传递? 的表示是数组 第五:Group by语句 第六:having 语句 第七:orderBy语句
上面,返回的值在一个Cursor中,如果要读数据,首先首先要调用cursor.moveToFirst从第一个开始,最好是加一个判断,以为如果 cursor为null,这个方法返回false。
This method will return false if the cursor is empty
然后就可以使用了:
cursor.moveToFirst();
long itemId = cursor.getLong(
    cursor.getColumnIndexOrThrow(FeedEntry._ID)
);

删除数据

删除数据要提供删除的行,像下面一样,防止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);

public int delete(String table,String whereClause, String[] whereArgs)
Returns

  • the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause. 


更新数据

下面是例子:
SQLiteDatabase db = mDbHelper.getWritableDatabase();

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

数据存储(2)使用SQL数据库

标签:

人气教程排行