kotlin 我的工作自动静音应用程序,有开始和结束时间

zdwk9cvp  于 2023-02-24  发布在  Kotlin
关注(0)|答案(1)|浏览(116)

和数据存储在房间数据库,但我想解决方案,如果开始和结束时间是相同的
有没有解决方案可以使数据库拒绝相同开始时间和结束时间

jmp7cifd

jmp7cifd1#

如果开始和结束时间相同怎么办
使用BETWEEN将返回一行,其中存储数据和查询的开始和结束都相同。
考虑下面的演示(这是最后一个查询,也就是结果2),剩下的只是在数据库中创建数据(结果1)。

/* Just in case Environment is dirty */
DROP TABLE IF EXISTS example;
/* Create the table */
CREATE TABLE IF NOT EXISTS example (startdatetime INTEGER, enddatetime INTEGER);

/* Load the table with some data */
WITH cte(onedatetime) AS (
        SELECT datetime('now') UNION ALL SELECT datetime(onedatetime,'+1 Hour') FROM cte LIMIT 10
    )
INSERT INTO example SELECT onedatetime,onedatetime FROM cte;

/* The data loaded */
SELECT * FROM example;

/* The demonstration */
SELECT * FROM example WHERE startdatetime BETWEEN (SELECT startdatetime FROM example ORDER BY startdatetime ASC LIMIT 1) AND (SELECT startdatetime FROM example ORDER BY startdatetime ASC LIMIT 1);
/* Clean Up Test Environment */
DROP TABLE IF EXISTS example;
    • 结果1**已加载的数据(请注意,由于日期时间基于当前日期时间,因此每次运行时数据都会发生变化):-

  • 请注意,突出显示的行将用于BETWEEN .... AND ....子句的两个值。
    • 结果2**

  • 子查询(SELECT startdatetime FROM example ORDER BY startdatetime ASC LIMIT 1)确保日期相同(按照示例表中第一行)
  • 显然,这没有什么用处,但可以用来说明何时开始和结束日期相同。

即,即使BETWEEN(开始和结束)的两个值相同,行仍然匹配。
假设example表被定义为Room中的@Entity,并且要传递开始和结束日期时间,则@Dao注解接口/抽象类中的函数可以类似于/基于:-

@Query("SELECT * FROM example WHERE startdatetime BETWEEN :startDateTime AND :endDateTime AND enddatetime BETWEEN :startDateTime AND :endDateTime;")
fun getExamplesBetweenDateTimes(startDateTime: String, endDateTime: String): List<Example>
    • 房间演示**

使用@Entity:-

@Entity
data class Example(
    @PrimaryKey
    val exampleId: Long?=null,
    val startdatetime: String,
    val enddatetime: String
)

除了上面的getExamplesBetweenDateTimes函数以及其他必要的代码(@Database注解抽象类,插入示例很有趣),然后使用:-

dbx = SO75530351DB.getInstance(this)
    daox = dbx.getDao()

    val dt01 = "2023-01-01 20:00"
    val dt02 = "2023-01-01 21:00"
    val dt03 = "2023-01-01 19:00"

    daox.insert(Example(startdatetime =  dt01, enddatetime =  dt01))
    daox.insert(Example(startdatetime =  dt01, enddatetime =  dt02))
    daox.insert(Example(startdatetime =  dt02, enddatetime =  dt02))
    daox.insert(Example(startdatetime =  dt02, enddatetime =  dt03))
    daox.insert(Example(startdatetime =  dt03, enddatetime =  dt03))

    for (e in daox.getExamplesBetweenDateTimes(dt01,dt01)) {
        Log.d(
            "DBINFO",
            "Example extracted where startdatetime is ${e.startdatetime} and enddatetime is ${e.enddatetime} ID is ${e.exampleId}"
        )
    }

结果:-

D/DBINFO: Example extracted where startdatetime is 2023-01-01 20:00 and enddatetime is 2023-01-01 20:00 ID is 1
  • 即,仅单个行匹配查询,即开始在2023-01-01 20:00之间并且结束也在2023-01-01 20:00之间 (除非考虑毫秒,否则通常不期望任何东西具有相同的开始和结束)
    • 解决方案**(解决方案)

有没有解决方案可以使数据库拒绝相同开始时间和结束时间
如果它是原生SQLite,那么可以使用CHECK约束以及**INSERT OR IGNORE**。然而,尽管Room支持INSERT OR IGNORE,例如@Insert(onConflict = OnConflictStrategy.IGNORE)。Room不通过注解提供对CHECK的支持(并非不可能实现(我相信))。
但是,以下内容可用于有效模拟检查:

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(example: Example): Long
@Query("")
fun insertRestrictedExample(example: Example): Long {
    if (example.startdatetime != example.enddatetime) return insert(example)
    return -1
}
  • 请注意,绝不会直接调用insert函数(除非需要使用相同的开头和结尾进行插入)
    • 相应地扩展演示**

例如,如果使用了以下内容:-

val dt01 = "2023-01-01 20:00"
    val dt02 = "2023-01-01 21:00"
    val dt03 = "2023-01-01 19:00"

    daox.insertRestrictedExample(Example(startdatetime =  dt01, enddatetime =  dt01))
    daox.insertRestrictedExample(Example(startdatetime =  dt01, enddatetime =  dt02))
    daox.insertRestrictedExample(Example(startdatetime =  dt02, enddatetime =  dt02))
    daox.insertRestrictedExample(Example(startdatetime =  dt02, enddatetime =  dt03))
    daox.insertRestrictedExample(Example(startdatetime =  dt03, enddatetime =  dt03))

    for (e in daox.getExamplesBetweenDateTimesButNotIfSameStartAndEndPassed(dt01,dt01)) {
        Log.d(
            "DBINFO1",
            "Example extracted where startdatetime is ${e.startdatetime} and enddatetime is ${e.enddatetime} ID is ${e.exampleId}"
        )
    }
    for (e in daox.getAllFromExample()) {
        Log.d(
            "DBINFO2",
            "Example extracted where startdatetime is ${e.startdatetime} and enddatetime is ${e.enddatetime} ID is ${e.exampleId}"
        )
    }
  • 即新的insertRestrcitedExample和提取ALL行的查询,则结果将为

:-

D/DBINFO2: Example extracted where startdatetime is 2023-01-01 20:00 and enddatetime is 2023-01-01 21:00 ID is 1
D/DBINFO2: Example extracted where startdatetime is 2023-01-01 21:00 and enddatetime is 2023-01-01 19:00 ID is 2

即现在仅将开始和结束不同的2行插入到数据库中。
您还可以使用AND :startDateTime <> :endDateTime防止提取任何具有相同结尾和开头的数据
例如:

@Query("SELECT * FROM example WHERE startdatetime BETWEEN :startDateTime AND :endDateTime AND enddatetime BETWEEN :startDateTime AND :endDateTime AND :startDateTime <> :endDateTime;")
fun getExamplesBetweenDateTimesButNotIfSameStartAndEndPassed(startDateTime: String, endDateTime: String): List<Example>

相关问题