在《开始使用》中,我们学习了如何创建 Database
实例以及定义你自己的数据库实体。现在我们将开始学习如何在 SQLlin 中编写 SQL 语句。
Database
类重载了类型为 <T> Database.(Database.() -> T) -> T
的函数操作符。当你调用该操作符函数时,它将产生一个 DatabaseScope (数据库作用域)。
没错,它是该操作符函数的 lambda 表达式参数。任何 SQL 语句都必须写在 DatabaseScope 内。并且当 DatabaseScope 结束的时候内部的 SQL 语句才会执行。
你已经知道, INSERT、DELETE、UPDATE 以及 SELECT SQL 语句用于操作表。所以在你编写你的 SQL 语句之前,你还需要获取一个 Table
实例,就像这样:
private val database = Database(name = "Person.db", path = getGlobalPath(), version = 1)
fun sample() {
database {
PersonTable { table ->
// 编写你的 SQL 语句...
}
}
}
PersonTable
由 sqllin-processor 生成,这是因为 Person
类被添加了 @DBRow
注解。任何添加了 @DBRow
注解的类都会生成一个 Table
object,它的名字为 类名 + 'Table'
。
现在让我们来进行真正的 INSERT 操作:
fun sample() {
database {
PersonTable { table ->
table INSERT Person(age = 4, name = "Tom")
table INSERT listOf(
Person(age = 10, name = "Nick"),
Person(age = 3, name = "Jerry"),
Person(age = 8, name = "Jack"),
)
}
}
}
INSERT 语句可以直接插入对象,你可以一次插入一个或多个对象。
DELETE 语句将会比 INSERT 语句稍微复杂。SQLlin 不像 Jetpack Room 一样直接删除对象,而是使用 WHERE 子句:
fun sample() {
database {
PersonTable { table ->
table DELETE WHERE(age GTE 10 OR (name NEQ "Jerry"))
}
}
}
让我们来理解 WHERE 子句。WHERE
函数接收一个 ClauseCondiction
作为参数。示例中的 age
和 name
用于表示列名,它们是 Table
类的扩展属性,它们的类型是
ClauseElement
,由 KSP 生成。
ClauseElement
拥有一系列表示相应的 SQL 操作(=
、>
、<
、LIKE
、IN
、IS
等等)的操作符。当一个 ClauseElement
调用一个操作符时我们将会得到一个
ClauseCondiction
。多个 ClauseCondiction
可以使用 AND
或 OR
操作符连接并产生一个新的 ClauseCondiction
。
SQL 操作符与 SQLlin 操作符的对应关系如下表:
SQL | SQLlin |
---|---|
= | EQ |
!= | NEQ |
< | LT |
<= | LTE |
> | GT |
>= | GTE |
BETWEEN | BETWEEN |
IN | IN |
LIKE | LIKE |
GLOB | GLOB |
OR | OR |
AND | AND |
有时候,我们想要删除表中的所有数据,这时 DELETE 语句可以省略 WHERE 子句:
DELETE FROM person
在 SQLlin 中我们可以这样写来达到同样的效果:
fun sample() {
database {
PersonTable { table ->
table DELETE X
}
}
}
X
是一个 Kotlin object
(单例)。
UPDATE 语句与 DELETE 语句相似,它同样使用一个 WHERE 子句来限制更新条件。但是 UPDATE 语句的不同点在于它拥有一个独特的 SET 子句:
fun sample() {
database {
PersonTable { table ->
table UPDATE SET { age = 5 } WHERE (name NEQ "Tom")
}
}
}
SET 子句与其他子句不同,它接收一个 lambda 表达式作为参数,你可以在 lambda 中给列设置一个新值。lambda 表达式中的 age
是一个由 KSP
生成的可写属性,并且它仅在 SET 子句中可用,它与 WHERE 子句中的只读属性 age
不同。
你也可以编写没有 WHERE 子句的 UPDATE 语句用于更新所有的行,但使用它的时候你应该谨慎。
在 SQLlin 中使用事务非常简单,你只需要使用 transaction {...}
包裹你的 SQL 语句:
fun sample() {
database {
transaction {
PersonTable { table ->
table INSERT Person(age = 4, name = "Tom")
table INSERT listOf(
Person(age = 10, name = "Nick"),
Person(age = 3, name = "Jerry"),
Person(age = 8, name = "Jack"),
)
table UPDATE SET { age = 5 } WHERE (name NEQ "Tom")
}
}
}
}
transaction {...}
是 Database
的成员函数,将它写在 TABLE(databaseName) {...}
函数的内部或外部没有特别限制。
你已经学习了如何使用 INSERT、DELETE 以及 UPDATE 语句,接下来你将学习 SELECT 语句。 SELECT 语句相比其他语句更复杂,做好准备哦 :)。