【问题标题】:SQLLite update doesn't update the table at all (Android Studio with Kotlin)SQLite 更新根本不更新表(带有 Kotlin 的 Android Studio)
【发布时间】:2019-10-04 09:07:01
【问题描述】:

我对 Android、Kotlin 和 SQLLite 还很陌生。

我已经创建了这个表。

val create = "CREATE TABLE IF NOT EXISTS $TABLE_NAME (" +
    "$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
    "$COLUMN_USERNAME STRING, $COLUMN_PASSWORD STRING, $COLUMN_EMAIL STRING, $COLUMN_LAST_LOGIN DATETIME NULL, " +
    "$COLUMN_PRIV_ACCESS_ADMIN_LIST BOOLEAN, $COLUMN_PRIV_CHANGE_ADMIN_LIST BOOLEAN, $COLUMN_PRIV_SEND_EMAIL_REPORT BOOLEAN, " +
    "$COLUMN_IS_ACTIVE BOOLEAN" +
    ")"
db.execSQL(create)

我可以通过这个成功添加新数据:

val values = ContentValues()

values.put(COLUMN_USERNAME, "admin")
values.put(COLUMN_PASSWORD, "password")
values.put(COLUMN_EMAIL, "test@test.com")
values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, true)
values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, true)
values.put(COLUMN_IS_ACTIVE, admin.isActive)

val db = this.writableDatabase
db.insert(TABLE_NAME, null, values)

我也可以用这个成功检索数据:

val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_NAME", null)

我得到的信息是我放在那里的数据的 ID = 1

但我无法使用以下代码将数据更改为其他内容:

val values = ContentValues()

values.put(COLUMN_USERNAME, "adminssss")
values.put(COLUMN_PASSWORD, "passwordsss")
values.put(COLUMN_EMAIL, "test@test.org")
values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, false)
values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, false)
values.put(COLUMN_IS_ACTIVE, true)

val db = this.writableDatabase
db.update(TABLE_NAME, values, "$COLUMN_ID=1", arrayOf())
// or
db.update(TABLE_NAME, values, "$COLUMN_ID=?", arrayOf("1"))

或者

val db = this.writableDatabase
val query = "UPDATE $TABLE_NAME " +
    "SET $COLUMN_USERNAME = 'adminssss', $COLUMN_PASSWORD = 'passwordsss', $COLUMN_EMAIL = 'test@test.org', " +
    "$COLUMN_PRIV_ACCESS_ADMIN_LIST = 0, " +
    "$COLUMN_PRIV_CHANGE_ADMIN_LIST = 1, " +
    "$COLUMN_PRIV_SEND_EMAIL_REPORT = 0, " +
    "$COLUMN_IS_ACTIVE = 1 " +
    "WHERE $COLUMN_ID = 1"
db.rawQuery(query, null)
// or
db.execQuery(query)

我对查询语言不太擅长,但我尝试仔细检查查询并没有发现任何问题。运行更新查询时,无论是上面示例中的哪个版本,都可以正常运行,但是当我再次重新选择数据时,什么都没有改变。数据与我第一次放入时保持不变。

有人可以帮忙吗?

【问题讨论】:

  • 使用 var cursor = db.rawQuery("SELECT * FROM $TABLE_NAME", null) 代替 val 并尝试。
  • @Jaymin 是一样的。游标在另一个函数上进行处理以提取数据并将其放入模型类的数组中,并将游标重新分配给var。我可以正确检索多行。
  • 你能把db.update(TABLE_NAME, values, "$COLUMN_ID=1", arrayOf())替换成db.update(TABLE_NAME, values, "${COLUMN_ID} = 1", arrayOf())
  • 如果你想在Android中使用数据库,我强烈推荐使用RoomDB,它更容易

标签: android sqlite kotlin sql-update android-sqlite


【解决方案1】:

您的第一个更新代码没有任何问题(两者都有效),它有效(参见下面的工作示例)。

我怀疑您的问题可能是您删除了一行并添加了另一行。在这种情况下,因为您已经对 AUTOINCREMENT 进行了编码,所以这样一行的 ID 不会是 1,而是可能是 2。

  • 您可以使用 logAll 函数检查基础行(如下面的工作示例中所使用的)。

如果使用工作示例中的代码,那么尝试使用 rawQuery 和 execQuery 的问题将变得毫无意义。

我相信您的问题是您如何查看结果(或如前所述)。考虑以下工作示例:-

工作示例

Database Helper 类,DBHelper.kt(基于可用代码)包括代码,例如更新为函数:-

class DBHelper(context: Context) : SQLiteOpenHelper(context, DBNAME, null, DBVERSION) {

    val all: Cursor
        get() = this.writableDatabase.query(TABLE_NAME, null, null, null, null, null, null)

    override fun onCreate(db: SQLiteDatabase) {

        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COLUMN_USERNAME + " STRING, " +
                COLUMN_PASSWORD + " STRING, " +
                COLUMN_EMAIL + " STRING, " +
                COLUMN_LAST_LOGIN + " DATETIME DEFAULT NULL, " +
                COLUMN_PRIV_ACCESS_ADMIN_LIST + " BOOLEAN, " +
                COLUMN_PRIV_CHANGE_ADMIN_LIST + " BOOLEAN," +
                COLUMN_PRIV_SEND_EMAIL_REPORT + " BOOLEAN, " +
                COLUMN_IS_ACTIVE + " BOOLEAN" +
                ")"
        )
    }

    fun add(
            username: String,
            password: String,
            email: String,
            privaccessadminlist: Boolean,
            privchangeadminlist: Boolean,
            privsendemailreport: Boolean,
            is_active: Boolean): Long {

        val cv = ContentValues()
        cv.put(COLUMN_USERNAME, username)
        cv.put(COLUMN_PASSWORD, password)
        cv.put(COLUMN_EMAIL, email)
        cv.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, privaccessadminlist)
        cv.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, privchangeadminlist)
        cv.put(COLUMN_PRIV_SEND_EMAIL_REPORT, privsendemailreport)
        return this.writableDatabase.insert(TABLE_NAME, null, cv)
    }

    fun logAll() {
        val csr = all
        var sb = StringBuilder()
        while (csr.moveToNext()) {
            sb = StringBuilder().append("Row is " + csr.position.toString())
            sb.append("\n\tUserName is :").append(csr.getString(csr.getColumnIndex(COLUMN_USERNAME)))
            sb.append("\n\tPasword is :").append(csr.getString(csr.getColumnIndex(COLUMN_PASSWORD)))
            sb.append("\n\tEmail is :").append(csr.getString(csr.getColumnIndex(COLUMN_EMAIL)))
            sb.append("\n\t PRIVACCESSAL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_ACCESS_ADMIN_LIST)) > 0).toString())
            sb.append("\n\t PRIVCHGAL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_CHANGE_ADMIN_LIST)) > 0).toString())
            sb.append("\n\t PRIVSNDEMAIL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_SEND_EMAIL_REPORT)) > 0).toString())
            Log.d("LOGDATA", sb.toString())
        }
    }

    // Suggested update code
    fun updateById(id: Long,
                   username: String,
                   password: String,
                   email: String,
                   privaccessadminlist: Boolean,
                   privchangeadminlist: Boolean,
                   privsendemailreport: Boolean,
                   is_active: Boolean): Int {
        val cv = ContentValues()
        cv.put(COLUMN_USERNAME, username)
        cv.put(COLUMN_PASSWORD, password)
        cv.put(COLUMN_EMAIL, email)
        cv.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, privaccessadminlist)
        cv.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, privchangeadminlist)
        cv.put(COLUMN_PRIV_SEND_EMAIL_REPORT, privsendemailreport)
        val whereclause = "$COLUMN_ID=?"
        val whereargs = arrayOf(id.toString())
        return this.writableDatabase.update(TABLE_NAME, cv, whereclause, whereargs)
    }

    //Your code
    fun update() {
        val values = ContentValues()

        values.put(COLUMN_USERNAME, "adminszzz")
        values.put(COLUMN_PASSWORD, "passwordzzz")
        values.put(COLUMN_EMAIL, "test@test.orgzzz")
        values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, false)
        values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
        values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, false)
        values.put(COLUMN_IS_ACTIVE, true)

        val db = this.writableDatabase
        db.update(TABLE_NAME, values, "$COLUMN_ID=1", arrayOf())
// or
        //db.update(TABLE_NAME, values, "$COLUMN_ID=?", arrayOf("1"))
    }


    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
    }

    companion object {

        val DBNAME = "mydb"
        val DBVERSION = 1

        val TABLE_NAME = "mytable"
        val COLUMN_ID = BaseColumns._ID
        val COLUMN_USERNAME = "username"
        val COLUMN_PASSWORD = "password"
        val COLUMN_EMAIL = "email"
        val COLUMN_LAST_LOGIN = "last_login"
        val COLUMN_PRIV_ACCESS_ADMIN_LIST = "priv_access_admin_list"
        val COLUMN_PRIV_CHANGE_ADMIN_LIST = "priv_change_admin_list"
        val COLUMN_PRIV_SEND_EMAIL_REPORT = "priv_send_email_report"
        val COLUMN_IS_ACTIVE = "is_active"
    }
}

还有一个 Activity 来调用函数 MainAvctivity.kt :-

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var dbhlpr = DBHelper(this)

        dbhlpr = DBHelper(this)
        dbhlpr.add("admin", "password", "test@test.com", true, true, true, true)
        dbhlpr.logAll()

        dbhlpr.updateById(1, "adminssss", "passwordsss", "test@test.org", false, true, false, true)
        dbhlpr.logAll()

        dbhlpr.update();
        dbhlpr.logAll();
    }
}

结果

运行时将以下内容输出到日志:-

2019-05-17 16:12:07.182 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
        UserName is :admin
        Pasword is :password
        Email is :test@test.com
         PRIVACCESSAL is true
         PRIVCHGAL is true
         PRIVSNDEMAIL is true
2019-05-17 16:12:07.184 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
        UserName is :adminssss
        Pasword is :passwordsss
        Email is :test@test.org
         PRIVACCESSAL is false
         PRIVCHGAL is true
         PRIVSNDEMAIL is false
2019-05-17 16:12:07.186 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
        UserName is :adminszzz
        Pasword is :passwordzzz
        Email is :test@test.orgzzz
         PRIVACCESSAL is false
         PRIVCHGAL is true
         PRIVSNDEMAIL is false

即有 3 个批次,每个批次都显示数据库中的单行。后两个表示数据已相应更新。

【讨论】:

  • 该代码实际上是原始代码的“评估”版本,其中包含变量和模型。但是值和生成的 SQL 与我在代码中所写的一样是真实的。奇怪的是,当我尝试新项目时,您放在一起的代码确实可以工作,但在放入现有项目时却无法正常工作。我想我的数据库设置或项目设置还有其他问题,但我不知道是什么。我最终想要的解决方案是实际删除具有该 id 的行,并使用相同的 id 重新创建。
  • @ChenLiYong 我怀疑问题是您删除了一行或多行。 AUTOINCREMENT 维护已用于 ID 列的最大值。如果第一行已在某个时间被删除,则 ID 将不是 1。我已尝试在答案中对此进行解释。
【解决方案2】:

更新操作后,您似乎没有通过调用 db.close() 方法关闭数据库。

关闭连接会刷新您所做的更改,否则,引擎会在执行此操作之前等待刷新时间。使用完连接后关闭连接是个好主意,以确保您的更改实际发送到商店。在写入之后和刷新之前断电会丢失数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 2020-08-02
    相关资源
    最近更新 更多