文章目录
CRUD
C 代表添加 (Create)
R代表查询(Retrieve)
U代表更新(Update)
D代表删除(Delete)
每一种操 作又各自对应了一种 SQL命令,如果你比较熟悉 SQL语言的话,一定会知道添加数据时使 用 insert,查询数据时使用 select,更新数据时使用 update,删除数据时使用 delete
但是开 发者的水平总会是参差不齐的,未必每一个人都能非常熟悉地使用 SQL语言,因此 Android 也是提供了一系列的辅助性方法,使得在 Android中即使不去编写 SQL语句,也能轻松完成 所有的 CRUD操作
前面我们已经知道,调用 SQLiteOpenHelper 的 getReadableDatabase()
或getWritableDatabase()
方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个 SQLiteDatabase 对象,借助这个对象就可以对数据进行 CRUD 操作了
添加数据
SQLiteDatabase 中提供了一个 insert()
方法,这个方法就是专门用于添加数据的
它接收三个 参数,第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字
第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值 NULL,一般我们用不到这 个功能,直接传入 null即可
第三个参数是一个 ContentValues对象,它提供了一系列的 put() 方法重载,用于向 ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加 数据传入即可
实践下,修改 activity_main.xml 中的代码,在布局文件中又新增了一个按钮
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data" />
修改MainActivity的代码
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(view -> {
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//开始组装第一组数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
//开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 510);
values.put("price", 19.95);
db.insert("Book", null, values);
});
在添加数据按钮的点击事件里面,我们先获取到了 SQLiteDatabase 对象,然后使用 ContentValues 来对要添加的数据进行组装。如果你比较细心的话应该会发现,这里只对 Book 表里其中四列的数据进行了组装,id那一列没并没给它赋值。这是因为在前面创建表的时候 我们就将 id列设置为自增长了,它的值会在入库的时候自动生成,所以不需要手动给它赋 值了
接下来调用了 insert()
方法将数据添加到表当中,注意这里我们实际上添加了两条数据, 上述代码中使用 ContentValues 分别组装了两次不同的内容,并调用了两次 insert()
方法
现在可以重新运行一下程序了,点击一下 Adddata 按钮,此时两条数据应该都已经添加成功了
验证一下,导出数据库,重新加载,双击 Book 表,弹出以下弹框
这个窗口是用来设置查询条件的,这里不设置任何查询条件,直接点击 No Filter
使用 Kotlin 实现
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val helper = MyDatabaseHelper(this, "BookStore.db", 1)
create_database.setOnClickListener {
helper.writableDatabase
}
add_data.setOnClickListener {
val db = helper.writableDatabase
val value1 = ContentValues().apply {
put("name","The Da Vinci Code")
put("author","Dan Brown")
put("pages",454)
put("price",16.96)
}
db.insert("Book",null,value1)
val value2 = ContentValues().apply {
put("name","The Lost Symbol")
put("author","Dan Brown")
put("pages",510)
put("price",19.95)
}
db.insert("Book",null,value2)
}
}
}
更新数据
SQLiteDatabase 中也是提供了一个非常好用的 update()
方法用于对数据进行更新,这个方法 接收四个参数,第一个参数和 insert()方法一样,也是表名,在这里指定去更新哪张表里的数据。第二个参数是 ContentValues 对象,要把更新数据在这里组装进去。第三、第四个参数 用于去约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行
activity_main.xml
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update data" />
布局文件中添加了一个用于更新数据的按钮。然后修改 MainActivity 中的代码
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(view -> {
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price","10.99");
db.update("Book",values,"name=?", new String[] { "The Da Vinci Code" });
});
这里在更新数据按钮的点击事件里面构建了一个 ContentValues 对象,并且只给它指定 了一组数据,说明我们只是想把价格这一列的数据更新成 10.99。然后调用了 SQLiteDatabase 的 update()
方法去执行具体的更新操作,可以看到,这里使用了第三、第四个参数来指定具 体更新哪几行。第三个参数对应的是 SQL语句的 where部分,表示去更新所有 name等于?
的行,而?
是一个占位符,可以通过第四个参数提供的一个字符串数组为第三个参数中的每 个占位符指定相应的内容。因此上述代码想表达的意图就是,将名字是 The DaVinci Code 的这本书的价格改成 10.99
点击一下 Update data按钮后,再次验证
使用 Kotlin 实现
update_data.setOnClickListener {
val db = helper.writableDatabase
val value = ContentValues().apply {
put("price", "10.99")
}
db.update("Book", value, "name=?", arrayOf("The Da Vinci Code"));
}
删除数据
SQLiteDatabase中提供了一个 delete()
方法专门用于删除数据,这个方法接收三个参数,第一 个参数仍然是表名,第二、第三个参数又是用于去约束删除某一 行或某几行的数据,不指定的话默认就是删除所有行
修改activity_main.xml中的代码,增加一个用于删除的 Button
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data" />
修改 MainActivity中的代码
Button deleteButton = (Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(v -> {
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[]{"500"});
});
我们在删除按钮的点击事件里指明去删除 Book 表中的数据,并且通过第二、 第三个参数来指定仅删除那些页数超过 500页的书籍。其中 The Lost Symbol这本书的页 数超过了 500页,也就是说当我们点击删除按钮时,这条记录应该会被删除掉
点击一下 Delete data按钮后,再次输入查询语句查看表中的数据情况
使用 Kotlin 实现
delete_data.setOnClickListener {
val db = helper.writableDatabase
db.delete("Book","pages > ?",arrayOf("500"))
}
查询数据
SQL的全称是 Structured Query Language
SQLiteDatabase 中还提供了一个 `query()方法用于对数据进行查询。 这个方法的参数非常复杂,最短的一个方法重载也需要传入七个参数
第一个参数不用说,当然还是表名
第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列
第三、第四个 参数用于去约束查询某一行或某几行的数据,不指定则默认是查询所有行的数据
第五个参 数用于指定需要去 groupby 的列,不指定则表示不对查询结果进行 groupby 操作
第六个参 数用于对 groupby 之后的数据进行进一步的过滤,不指定则表示不进行过滤
第七个参数用 于指定查询结果的排序方式,不指定则表示使用默认的排序方式
更多详细的内容可以参考 下表
虽然 query()
方法的参数非常多,但我们不必为每条查询语 句都指定上所有的参数,多数情况下只需要传入少数几个参数就可以完成查询操作了。调用query()
方法后会返回一个 Cursor 对象,查询到的所有数据都将从这个对象中取出
修改main_activity.xml
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data" />
修改MainActivity中代码
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(view -> {
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
//查询Book表中所有数据
Cursor cursor = db.query("Book",null,null,null,null,null,null);
if(cursor.moveToFirst()){
do{
//遍历Cursor对象,取出数据并打印
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int page = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","book name is "+name);
Log.d("MainActivity","book author is "+author);
Log.d("MainActivity","book pages is "+page);
Log.d("MainActivity","book price is "+price);
}while (cursor.moveToNext());
}
cursor.close();
});
我们首先在查询按钮的点击事件里面调用了 SQLiteDatabase 的 query()
方法 去查询数据
这里的 query()
方法非常简单,只是使用了第一个参数指明去查询 Book表,后 面的参数全部为 null。这就表示希望查询这张表中的所有数据,虽然这张表中目前只剩下一 条数据了
查询完之后就得到了一个 Cursor 对象,接着我们调用它的 moveToFirst()
方法将数据的指针移动到第一行的位置,然后进入了一个循环当中,去遍历查询到的每一行数据。在 这个循环中可以通过 Cursor的 getColumnIndex()方法获取到某一列在表中对应的位置索引, 然后将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了。接着我 们使用 Log 的方式将取出的数据打印出来,借此来检查一下读取工作有没有成功完成。最后 别忘了调用 close()
方法来关闭 Cursor
使用 kotlin 实现
query_data.setOnClickListener {
val db = helper.writableDatabase
val cursor = db.query("Book", null, null, null, null, null, null)
if (cursor.moveToFirst()) {
do {
val name = cursor.getString(cursor.getColumnIndex("name"))
val author = cursor.getString(cursor.getColumnIndex("author"))
val page = cursor.getString(cursor.getColumnIndex("pages"))
val price = cursor.getString(cursor.getColumnIndex("price"))
Log.d("MainActivity", "book name is " + name);
Log.d("MainActivity", "book author is " + author);
Log.d("MainActivity", "book pages is " + page);
Log.d("MainActivity", "book price is " + price);
} while (cursor.moveToNext())
}
cursor.close()
}
使用 SQL操作数据库
虽然 Android已经给我们提供了很多非常方便的 API 用于操作数据库,不过总会有一些 人不习惯去使用这些辅助性的方法,而是更加青睐于直接使用 SQL 来操作数据库
下面直接用SQL完成前面的CRUD操作。分别使用 java 和 kotlin 实现
添加数据
db.execSQL("insert into Book (name,author,pages,price) values(\"The Da Vinci Code\",\"Dan Brown\",\"454\",\"16.96\")");
db.execSQL("insert into Book (name,author,pages,price) values(\"The Lost Symbol\",\"Dan Brown\",\"510\",\"19.955\")");
或者
db.execSQL("insert into Book (name,author,pages,price) values (?,?,?,?)", arrayOf("The Da Vinci Code","Dan Brown","454","16.96"))
更新数据
db.execSQL("update Book set price = \"10.99\" where name = \"The Da Vinci Code\"");
或者
db.execSQL("update Book set price = ? where name = ?", arrayOf("10.99","The Da Vinci Code"))
删除数据
db.execSQL("delete from Book where pages > 500");
或者
db.execSQL("delete from Book where pages > ?", arrayOf("500"))
查询数据
db.rawQuery("select * from Book",null);
或者
val cursor = db.rawQuery("select * from Book",null)
除了查询数据的时候调用的是 SQLiteDatabase 的 rawQuery()
方法,其他的操 作都是调用的 execSQL()
方法。以上演示的几种方式,执行结果会和前面几小节中我们学习 的 CRUD操作的结果完全相同,选择使用哪一种方式就看你个人的喜好了