问题
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