一、创建数据库
1、SQLiteOpenHelper
Android 提供了SQLiteOpenHelper
这个抽象类对数据库创建和升级,必须要重写onCreate()
和onUpgrade()
才行
这个类有两个重要实例方法,getReadableDatabase()
和getWritableDatabase()
,两者都能打开数据库【存在则打开,否则创建后打开】,并返回一个可供读写操作的对象。当数据库不可被写入的时候,getReadableDatabase()
会以只读的方式打开数据库,getWritableDatabase()
则抛出异常
这个类有构造方法可供重写,其有四个参数:
Context
:上下文对象- 数据库名,创建数据库指定的名称
- 一般传入
null
- 数据库版本号,用于数据库升级
数据库文件默认存储位置:/data/data/<package name>/databases/
2、实战
新建一个空项目:
day12_DatabaseTest
a. SQL
建一张BookStore.db
数据库,其有一张Book
表,SQL语句如下:
create table Book(
id integer primary key autoincrement,
author text,
price real,
pages integer,
name text)
real
表示浮点型,blob
表示二进制型
在代码中执行这段语句,需要新建MyDatabaseHelper
类继承自SQLiteOpenHelper
,代码如下:
ublic class MyDatabaseHelper extends SQLiteOpenHelper {
private Context mContext;
public static final String CREATE_BOOK = "create table Book( id integer primary key autoincrement, author text, price real, pages integer, name text)";
public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "创建完成!", Toast.LENGTH_SHORT).show();
}
}
b. 主页
主布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建数据库"
android:id="@+id/create_database"/>
</LinearLayout>
主活动
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
}
}
c. 运行
多次点击按钮,会发现这里的Toast
只会弹出一次,因为数据库已经建好了
查看数据库文件:
我们可以看到数据库BookStore.db
,那么它里面的数据表数和查看呢?
d. 查看数据表
查看数据表需要adb工具
,adb工具
在Android SDK
下的platform-tools
目录下,为了便于使用它,想把它的路径添加到环境变量:
打开命令行,输入adb shell
就能进入控制台,输入su
切换超级管理员:
接下来cd
到数据库目录下:
输入sqlite3 数据库名
就能打开数据库
查看有哪些表:.table
查看建表语句:.schema
android_metadata
和sqlite_sequence
是自动创建的表,不用管
最后.exit
退出
二、升级数据库
任务:再添加一个Category
表在数据库里,建表语句
create table Category(
id integer primary key autoincrement,
category_name text,
category_code integer)
1、要注意的问题
- 原来的数据库已经存在了,那么再次Create
onCreate()
也不会执行,那么新的表就无法创建了 - 因此,我们要定义
onUpgrade()
逻辑:当存在旧的表时,就删除旧的表,再执行onCreate()
重新建表 - 如何让
onUpgrade()
执行呢,修改SQLiteOpenHelper
的构造方法第四个参数,版本号改大就行
2、实战
在代码中修改MyDatabaseHelper
类继承自SQLiteOpenHelper
,代码如下:
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context mContext;
public static final String CREATE_BOOK = "create table Book( id integer primary key autoincrement, author text, price real, pages integer, name text)";
public static final String CREATE_CATAGORY = "create table Category( id integer primary key autoincrement, category_name text, category_code integer)";
public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATAGORY);
Toast.makeText(mContext, "创建完成!", Toast.LENGTH_SHORT).show();
}
}
主活动只需要改一下版本号:
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
运行的的时候发现,也是点击一次有Toast
,多次点击并没有Toast
,这是因为版本号的限制
最后在adb
下查看数据表:
三、增
SQLiteOpenHelper.insert()
三个参数:
- 参数一:表名
- 参数二:传
null
- 参数三:
ContentValues
对象,提供了一系列的put()
方法重载,传入列名和数据就行
1、主布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
......
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="增"
android:id="@+id/insert"/>
</LinearLayout>
2、主活动
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
Button createDatabase = findViewById(R.id.create_database);
Button button_insert = findViewById(R.id.insert);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
button_insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 第一条数据
values.put("name", "老人与海");
values.put("author", "海明威");
values.put("pages", 456);
values.put("price", 18.88);
db.insert("Book", null, values);
values.clear();
// 第二条数据
values.put("name", "绿野仙踪");
values.put("author", "莱曼·弗兰克·鲍姆");
values.put("pages", 345);
values.put("price", 16.66);
db.insert("Book", null, values);
}
});
}
}
3、运行
点击三下增按钮:
在adb
中查一下,果然增加了三组:
四、改
SQLiteOpenHelper.update()
四个参数:
- 参数一:表名
- 参数二:
ContentValues
对象,提供了一系列的put()
方法重载,传入列名和数据就行 - 参数三、参数四用于约束,限制某一行或某几行的数据,不指定则是更新所有行
1、主布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
。。。。。。
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="改"
android:id="@+id/update"/>
</LinearLayout>
2、主活动
Button button_update = findViewById(R.id.update);
button_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book",values, "name = ?",new String[]{"老人与海"});
}
});
第三个参数对应SQL语句中的where
部分,表示更新所有name
= ?
的行,?
是个占位符,即第四个参数提供的字符数组的第一个数即对应内容。
完整意义:
在Book
表中,把name
等于 老人与海
的行的price
修改为10.99
3、运行
点击一下改按钮:
相应三行的数据都被修改【之前的截图也放到一起,便于对比
】:
五、删
SQLiteOpenHelper.delete()
三个参数:
- 参数一:表名
- 参数二、参数三用于约束,限制某一行或某几行的数据,不指定则是删除所有相应行
修改主布局~
修改主活动:
Button button_delete = findViewById(R.id.delete);
button_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
db.delete("Book", "pages > ?", new String[]{"400"});
}
});
运行:
六、查
SQLiteOpenHelper.quary()
七个参数:
- 参数一:
table
,表名 - 参数二:
columns
,列名 - 参数三:
selection
,where约束条件 - 参数四:
selectionArgs
,占位符提供值 - 参数五:
groupBy
,分组查询 - 参数六:
having
,进一步约束 - 参数七:
orderBy
,排序方式 - 会返回
Cursor
对象,查询到的数据从这个对象中取出
主布局修改~
主活动修改:
Button button_quary = findViewById(R.id.quary);
button_quary.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
// 查询表中所有的数据
Cursor cursor = db.query("Book",null, null, null, null, null, null);
if (cursor.moveToFirst()){
do{
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d(TAG, "--------------------");
Log.d(TAG, "书名:"+name);
Log.d(TAG, "作者:"+author);
Log.d(TAG, "页数:"+pages);
Log.d(TAG, "价格:"+price);
Log.d(TAG, "--------------------");
}while (cursor.moveToNext());
}
cursor.close();
}
});
别忘了最后要关闭cursor
运行:
七、使用SQL操作数据库
艹,前面的白学了,使用下面这个最简单
1、增
db.execSQL("insert into 表名(列1,列2,列3...) values (值1,值2,值3...)")
2、删
db.execSQL("delete from 表名 wherr 列名 > ?", new String[]{值})
3、改
db.execSQL("update 表名 set 列名 = ? where 列名 > ?", new String[]{值1,值2})
4、查
db.rawQuery("select * from Book", null);