SQLite无显式行索引列时,如何用嵌套SQL按行索引删除指定行?
解决按行索引删除SQLite指定行的问题
为什么原语句会删除所有行
你的SQL语句逻辑存在错误:EXISTS (SELECT * FROM myTable LIMIT 1 OFFSET $rowindex) 子句只要能找到第rowindex行,就会返回true,导致DELETE FROM myTable WHERE EXISTS(...)的条件对表中所有行都成立,最终删除全部数据。
正确的删除实现方式
SQLite每张表默认包含隐藏的ROWID列(若表未指定INTEGER PRIMARY KEY类型的主键,或主键为此类型,则主键字段会映射到ROWID)。你可以通过行索引定位目标行的唯一标识(如ROWID或自定义主键),再执行删除操作。
方法1:通过ROWID删除(推荐)
先查询指定偏移量行的ROWID,再根据ROWID精准删除:
fun delete(rowIndex: Int) { val db = databaseHelper.writableDatabase // 获取目标行的ROWID val cursor = db.rawQuery("SELECT ROWID FROM myTable LIMIT 1 OFFSET ?", arrayOf(rowIndex.toString())) if (cursor.moveToFirst()) { val rowId = cursor.getLong(cursor.getColumnIndex("ROWID")) // 根据ROWID执行删除 db.delete("myTable", "ROWID = ?", arrayOf(rowId.toString())) } cursor.close() db.close() }
方法2:用子查询匹配自定义主键
如果你的表有自定义主键(比如id字段),可以直接通过子查询获取目标行的主键再删除:
fun delete(rowIndex: Int) { val db = databaseHelper.writableDatabase // 假设主键字段为id,子查询定位目标行的id db.execSQL("DELETE FROM myTable WHERE id = (SELECT id FROM myTable LIMIT 1 OFFSET ?)", arrayOf(rowIndex)) db.close() }
注意:始终使用参数化查询(
?占位符),避免直接拼接字符串引发SQL注入风险。
关于ROW ID列布局空白的解决
隐藏ROW ID列后仍有空白,通常是因为你设置了View.INVISIBLE(该属性会保留View的布局空间),应改为设置View.GONE,让View完全从布局中移除:
val rowIdView = findViewById<TextView>(R.id.row_id_view) rowIdView.visibility = View.GONE
如果是动态生成表格行,直接不添加ROW ID对应的TextView,从根源避免布局空白。
内容的提问来源于stack exchange,提问作者ThN
相关产品推荐
相关产品推荐

