java - Android 中的 SQLite “after update” 触发器似乎不会在每次记录更新后运行

标签 java android sqlite triggers android-sqlite

问题: 什么(如果有)可能导致 SQLite 触发器仅在某些时候运行?

摘要:我从用 SQLite 编写的新触发器中得到了看似不一致的结果,我想了解是否因为我在 SQL 中犯了错误而发生了这种情况/Java 代码或者我可能遇到过 SQL 触发器可能无法按预期工作的罕见情况。

详细信息: 在处理 Android 项目时,我遇到了我最初认为是 SQLite 触发器的问题。但是,由于我的新触发器与同一项目中的其他几个工作触发器完全匹配(表名称除外),我开始怀疑是否是我的 Java 代码出了问题。

我遇到问题的触发器的目的是监视 TableA 的更改,例如在 DismissDateUTC 列中添加值。当对 TableA 中的任何数据进行更新时,触发器应该将更新的 TableA 记录的 ID 放入 TableAChanges 中,稍后用于确定哪些记录已更新并应发送回 Web 服务器。

当使用数据库检查器(在 Android Studio v4.2.1 中)或程序“DB Browser for SQLite”并手动在 TableA 上运行更新查询时,触发器完全按照预期工作,并且记录显示在 TableAChanges 中。当我以编程方式更新 TableA 时,触发器似乎没有运行。我相信它没有运行,因为在更新写入 TableA 后,没有记录写入 TableAChanges。

到目前为止我尝试过的事情:

  • 在 Android 7.1.1 设备上运行应用(触发器不起作用)
  • 在 Android 8.1.0 设备上运行应用(触发器不起作用)
  • 在 Android 11 设备上运行应用(触发器不起作用)
  • 通过 Android Studio DB Inspector 对 TableA 运行手动更新查询(触发器正在工作)
  • 从 DB Browser for SQLite 对 TableA 运行手动更新查询(触发器正在工作)
  • 通过“amitshekhar”从 Android 调试数据库对 TableA 运行手动更新查询(触发器正在工作)

表和触发器 SQL:

CREATE TABLE TableA (
    ID INTEGER PRIMARY KEY NOT NULL 
    -- (more table columns) --
    , DismissDateUTC TEXT NULL
);

CREATE TABLE TableAChanges (
    ID INTEGER PRIMARY KEY NOT NULL
);

CREATE TRIGGER trigTableA_U AFTER UPDATE ON TableA
BEGIN
    REPLACE INTO TableAChanges(ID)
        SELECT old.ID;  
END

TableA DAO 类中的 Android Java:

public boolean saveChanges() {
    boolean ret = true;
    
    ContentValues cv = new ContentValues();
    cv.put("ID", mId);
    // (more table columns)
    cv.put("DismissDateUtc", mDismissDateUtc);

    SQLiteDatabase db = DB.getInstance().getWritableDatabase();
    try {
        db.replaceOrThrow("TableA", null, cv);
    } catch (SQLException e) {
        ExceptionDao.logToAcra(e);
        ret = false;
    } finally {
        db.close();
    }
    
    return ret;
}

*** 为了透明起见,我已经知道可以通过手动将记录写入 TableAChanges 来解决此问题。不过,我还是想在这里提出这个问题,因为我希望了解这个问题的原因,而不是忽视这个问题。

最佳答案

触发器不起作用的原因是它是 AFTER UPDATE触发器,即只有在表更新后才会起作用。

另一方面,replaceOrThrow() 不更新表格。
它实际上正在执行INSERT OR REPLACE INTO...或者简单地REPLACE INTO...如果新 ID 则在表中插入新行的语句表中尚不存在,或者如果存在,则删除包含现有 ID 的行并插入新行。

关于java - Android 中的 SQLite “after update” 触发器似乎不会在每次记录更新后运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67940241/

相关文章:

iphone - 将图像存储到sqlite数据库中

java - 获取在 try 方法中设置的 Java bean

java - 尝试在空对象引用上调用虚拟方法 'int java.util.Random.nextInt(int)' [Android]

java - 我需要有人告诉我代码中的逻辑有什么问题

android - 适用于 Android/iphone/ipad 的开源或其他 pgp/gpg 库

android - 如何找到在 Android softKeyboard 上按下的是哪个键?

java - 如何从第一个 Activity 的 TextView 获取数据并从另一个 Activity 发布数据?

java - ZipInputStream 和 DigestInputStream 不能一起工作

sqlite - 使recoll索引sqlite文件

python - SQLITE 数据库表差异