数据库从SQLite开始
论SQLite的操作
Section titled “论SQLite的操作”ROOM是谁,我在哪,我的大脑呢
Section titled “ROOM是谁,我在哪,我的大脑呢”操作基本靠exeSQL(就是直接用SQL
SQL是不分大小写的
有时工具不一定靠谱,真正重要的是靠自己的判断
| 通过API | 通过SQL | |
|---|---|---|
| 增表 | create table 表名 (一堆值的名及[类型]) | |
| 增数据 | db.insert(表名, null, 值) | insert into 表名 (键) values(值) |
| 删表 | drop table [条件] 表名 | |
| 删数据 | db.delete("表名, 条件", 条件的值) | delete from 表名 where 条件 |
| 改 | db.update(表名, 要修改的列, 条件), arrayOf(值) | update 表名 set 列名 = ? where 条件 |
| 查 | db.query(表名, 列名, 条件, 条件中的具体值, 要分组的列, 分组的筛选条件, 搜索结果的排序方式) | select 列名 from 表名 where 条件 …… |
操作数据库那就得先有一个,原始的办法是弄个SQLiteOpenHelper,比如下面这样
class NoteDatabaseHelper(val context: Context, name: String, version: Int) :SQLiteOpenHelper(context, name, null, version)这样在别的文件中,可以通过两行代码来用这个Helper
val dbHelper = NoteDatabaseHelper(context, "数据库名", 版本)val db = dbHelper.writableDatabase这个db就是可以操作的数据库了
增(insert)
Section titled “增(insert)”创建一个新表可以像下面这样:
create table Note ( id integer primary key autoincrement, title text, content text, editTime)也就是create table 表名 (一堆值的名及类型(可选))
如果想要默认值,可以在类型后面加上NOT NULL DEFAULT 默认值
往表里面插入新的数据如下
val value = ContentValues().apply { put("title", binding.titleBox.text.toString()) put("content", binding.editBox.text.toString()) put("editTime", System.currentTimeMillis())}db.insert("Note", null, value)在kt里面可以这样组装一个数据再插入,插入不过就是db.insert(表名, null, 值)
除此之外,插入还可以用insertWithOnConflict,用来处理可能出现的冲突,只要在最后多加一个参数,比如
db.insertWithOnConflict("word", null, values, SQLiteDatabase.CONFLICT_IGNORE) // 忽略相同id这样就是当主键冲突时忽略然后继续插入
直接用SQL那就是insert into 表名 (键) values(值)后面再填值,例如
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", arrayOf("The Da Vinci Code", "Dan Brown", "454", "16.96"))看得出来一个?对应一个值
删(delete)
Section titled “删(delete)”就是db.delete("表名, 条件", 条件的值),比如
db.delete("Book", "pages > ? ", arrayOf("500"))用SQL则是delete from 表名 where 条件,后面跟上一串条件,如
db.execSQL("delete from Book where pages > ?", arrayOf("500"))删表则是drop table [条件] 表名 ,像是
drop table Note改(update)
Section titled “改(update)”修改数据用的是update,像db.update("Book", values, "name = ?", arrayOf("The Da Vinci Code"))
即db.update(表名, 要修改的列, 条件), arrayOf(值),其中要修改的列和条件和值都可以不止一个
用SQL就变成了
update 表名 set 列名 = ? where 条件后面一样用arrayOf填入值即可
查(select/query)
Section titled “查(select/query)”查可麻烦了,有一大堆参数
db.query(表名, 列名, 条件, 条件中的具体值, 要分组的列, 分组的筛选条件, 搜索结果的排序方式)
如果换成用参数名表示就是
db.query(table, columns, selections, selectionArgs, groupBy, having, orderBy)
使用having时必须也要有groupBy否则会狠狠报错
一般情况下都是用不到那么多个参数的,所以不要的地方用null填满就好了,比如
val cursor = db.query("Book", null, null, null, null, null, null)用SQL上面这句可以简化成
val cursor = db.rawQuery("select * from Book", null)要一行一行查询数据可以这样
if (cursor.moveToFirst()) { do { val name = cursor.getString(cursor.getColumnIndex("name")) val author = cursor.getString(cursor.getColumnIndex("author")) val pages = cursor.getInt(cursor.getColumnIndex("pages")) val price = cursor.getDouble(cursor.getColumnIndex("price")) } while (cursor.moveToNext())}cursor.close() // 最后别忘了关掉不过用getColumnIndexOrThrow比用getColumnIndex要更安全,不然有可能直接得到-1崩掉
在查询数据时一定要先用moveToFirst()转到第一个符合条件的数据,不然会狠狠地报错!
有关更多SQL语句
Section titled “有关更多SQL语句”id BETWEEN A AND B可以查询所有符合A≤id≤B的行
DESC代表倒序查找
事务(transaction)
Section titled “事务(transaction)”事务让一组操作只有全部执行完才会生效,有一个操作失败了就要全部打回
通过db.beginTransaction()就可以开启一个事务了
db.setTransactionSuccessful()说明事务完成,而db.endTransaction()代表事务结束
显然如果事务不完成那即使结束了前面对数据库的操作会全部木大
可以像下面这样用事务
db.beginTransaction()try{ ... db.setTransactionSuccessful()} catch (...) { ...} finally { db.endTransaction()}好耶!这样SQLite的基础操作就学完了,接下来的步骤是……学别的数据库框架,然后就不用这些语法了?!
不过那些框架都是基于SQLite写的,至少能知道面对的是个啥罢
下一集:LitePal我来辣!
下下一集:解析失败重回SQLite