【问题标题】:Can execSQL supports multiple sql statementsexecSQL能否支持多条sql语句
【发布时间】:2020-12-05 21:11:28
【问题描述】:

execSQL 可以支持多条语句还是我应该执行单独的命令。我的用例是在事务的上下文中。

fun update(id: Long, roles: List<Role>): Int? {
    val values = (roles.map { role -> "($id, ${role.id})" }).joinToString(",")

    val sql = "BEGIN TRANSACTION; DELETE FROM user_role WHERE user_id = $id;" + (if (values.count() > 0) "INSERT INTO user_role(user_id, role_id) VALUES$values; " else "") + "COMMIT;"

    connection.writableDatabase.execSQL(sql)

    return connection.readableDatabase.rawQuery("SELECT changes()", null).use { cursor ->
        return@use cursor.count
    }
}

可行的替代方法如下。

fun update(id: Long, roles: List<Role>): Int? {
    val values = (roles.map { role -> "($id, ${role.id})" }).joinToString(",")

    connection.writableDatabase.execSQL("BEGIN TRANSACTION;")
    connection.writableDatabase.execSQL("DELETE FROM user_role WHERE user_id = $id;")

    if (values.count() > 0) connection.writableDatabase.execSQL("INSERT INTO user_role(user_id, role_id) VALUES$values")
    connection.writableDatabase.execSQL("COMMIT")

    return connection.readableDatabase.rawQuery("SELECT changes()", null).use { cursor ->
        return@use cursor.count
    }
}

尝试捕捉方法

fun update(id: Long, roles: List<Role>): Int? {
    try {
        connection.writableDatabase.execSQL("BEGIN TRANSACTION;")
        connection.writableDatabase.execSQL("DELETE FROM user_role WHERE user_id = $id;")

        val values = (roles.map { role -> "($id, ${role.id})" }).joinToString(",")

        if (values.count() > 0) connection.writableDatabase.execSQL("INSERT INTO user_role(user_id, role_id) VALUES$values")
        connection.writableDatabase.execSQL("COMMIT") 
    } catch(exception: Exception) {
        connection.writableDatabase.execSQL("ROLLBACK")
        return null
    }

    return connection.readableDatabase.rawQuery("SELECT changes()", null).use { cursor ->
        return@use cursor.count
    }
}

【问题讨论】:

    标签: android sqlite


    【解决方案1】:

    没有。

    execSQL() 只执行单个语句。第一个 ; 之后的任何内容都会被忽略。


    好的,是否已知 execSQL 会抛出错误,以防万一出现问题以便我可以执行回滚,我应该将它包含在 try catch 块中吗?

    是的,它可以抛出异常。事务的规范模式类似于(Java 但在 Kotlin 中的想法是相同的):

    db.beginTransaction();
    try {
        // db operations that can throw and should be executed atomically
    
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
    

    这个想法是endTransaction() 是一个回滚,除非事务在 try 块结束时设置为成功。

    【讨论】:

    • 好的,是否 execSQL 会抛出错误,以防万一出现问题以便我可以执行回滚,我是否应该将其包含在 try catch 块中?
    • 是的,我同意这个beginTransaction,因为我以前使用过它,但是在我的示例中使用了原始sql,你同意我的方法吗??
    • 您的方法在调用 commit 的 finally 块中存在问题,如果您已经在 catch 块中回滚了事务,则没有事务。
    • 是的,你有一个观点,已编辑,可以吗?
    • 更好,尽管仍有一些边缘情况,例如提交抛出
    猜你喜欢
    • 2010-11-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 2016-12-19
    • 1970-01-01
    相关资源
    最近更新 更多