jiichan.com

PROGRAMMING

Android Kotlin
javascript
PHP
Java

Room での SQL いろいろ

Room では SQL の記述が他のデータベースと微妙に違うように感じます。
標準的な書き方でいいと思っても期待した結果がでません。そこで解決した書き方をメモっておくことにしました。(2025.06.19)

≪開発環境≫
windows11
andriod studio Ladybug

01. INSERT時にAUTO_INCREMENTで自動付与されたナンバーを取得する

SQL では無いがたまに必要になるので忘れないようにメモっておきます。
関数の戻り値に Long を指定すると取得できるようになります。

Dao

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMember(user: Users): Long // Insert 操作後の ID を取得

Repository

suspend fun insertMember(userName: String, telNumber: String): Long {
    return dao.insertMember(Users(0, userName, telNumber, false))
}
ViewModel

fun insertMember() {
    viewModelScope.launch {
        val userName = userNameState.text.toString()
        val telNumber = telNumberState.text.toString()
        // Insert をして更にインクリメントされた ID を取得
        val id = repo.insertMember(userName, telNumber) 
        // 取得した ID を別な Insert に使う
        repo.insertGroupMember(it, id.toInt())  
    }
}

02. AテーブルのカラムでBテーブルのカラムを更新する

これ例もなかなか実現できませんでした。Stack Overflow でも色んな例がありましたが次の SQL だけが上手くいきました。

Dao

// Groups テーブルの flag で Users テーブルの flag を更新する
@Query("UPDATE users SET flag = " +
"(SELECT gFlag FROM groups WHERE gName = :gName AND userId = gUserId) " +
"where EXISTS " +
"(SELECT gUserId FROM groups WHERE gName = :gName AND userId = gUserId)")
suspend fun updateFlagGtoU(gName: String)

03. 抽出するカラムに合わせてデータクラスを作る

INNER JOIN などでの複数テーブルからの抽出や、単数テーブルからの一部カラム抽出では 必ず抽出カラムに合わせてデータクラスを作成する。

Dao

@Query("SELECT u.userId, u.userName, g.gUserId, g.gName, g.gFlag " +
"FROM groups g INNER JOIN users u ON g.gUserId = u.userId WHERE gName = :group")
fun getGroupMembers(group: String): Flow>
    
UserAndGroup データクラス

data class UserAndGroup(
    val userId: Int,
    val userName: String,
    val gUserId: Int,
    val gName: String,
    val gFlag: Boolean = true
)

04. IN句のパラメータ

IN句のように個数が変化するパラメータはリストにするとよい。

Dao

@Query("SELECT * FROM users WHERE userId IN (:userIds)")
fun getUsersByIds(userIds: List): List

まとめ

これからも新たに知った SQL など Dao の書き方があれば追記していきます。