Can execSQL supports multiple sql statements

蹲街弑〆低调 提交于 2021-01-29 11:20:25

问题


Can execSQL supports multiple statements or shall i execute separate commands. My use case is in context of transactions.

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
    }
}

The alternate approach which works is as follows.

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
    }
}

TRY CATCH APPROACH

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
    }
}

回答1:


Nope.

execSQL() only executes single statements. Anything after the first ; is ignored.


okay, is execSQL known to throw errors, just in case if there's an issue so i can execute rollback, shall I include it in a try catch block?

Yes it can throw exceptions. The canonical pattern for transactions is something along the lines of (Java but the idea is the same in Kotlin):

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

    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

The idea is that endTransaction() is a rollback unless the transaction is set as successful at the end of the try block.



来源:https://stackoverflow.com/questions/65162002/can-execsql-supports-multiple-sql-statements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!