问题:如果有什么原因,会导致SQLite触发器只运行一部分时间?
摘要:我用SQLite编写的一个新触发器的结果似乎不一致,我想知道这是因为我在SQL/Java代码中犯了一个错误,还是因为我可能遇到了SQL触发器可能无法按预期工作的罕见情况。
详细信息:在安卓项目中,我遇到了最初认为是SQLite触发器问题的问题。然而,由于我的新触发器与同一项目中的其他几个工作触发器完全匹配(除了表名(,我开始怀疑我的Java代码是否是问题所在。
我遇到问题的触发器的目的是监视对TableA的更改,例如在DismissDateUTC列中添加值。当对TableA中的任何数据进行更新时,触发器应该将更新后的TableA记录的ID放入TableAChanges中,TableAChange稍后用于确定哪些记录已更新并应发送回web服务器。
当使用数据库检查器(在Android Studio v4.2.1中(或程序"DB Browser for SQLite"并手动在TableA上运行更新查询时,触发器会完全按照预期工作,并且记录会显示在TableA更改中。当我以编程方式更新TableA时,触发器似乎不会运行。我认为它没有运行,因为在将更新写入TableA之后,没有记录写入TableA更改。
到目前为止我尝试过的东西:
- 在Android 7.1.1设备上运行应用程序(触发器不起作用(
- 在Android 8.1.0设备上运行应用程序(触发器不起作用(
- 在Android 11设备上运行应用程序(触发器不起作用(
- 从Android Studio DB Inspector在TableA上运行手动更新查询(触发IS工作(
- 从DB Browser for SQLite在TableA上运行手动更新查询(触发IS工作(
- 通过"amitshekhar"在Android调试数据库的TableA上运行手动更新查询(触发IS工作(
表和触发器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
的行并插入新行。