SQLite changes()计算不变的UPDATE

时间:2014-10-15 00:10:00

标签: sql sqlite

我对SQLite的changes()函数有疑问,根据documentation返回最近完成的INSERT更改或插入或删除的数据库行数, DELETE或UPDATE语句“(另请参阅documentation of the underlying C/C++ function)。

我希望使用此函数来检查执行与单行有关的UPDATE语句确实是否导致该行被更改。 通过更改,我不仅仅意味着该行与语句的WHERE子句匹配。不,我的意思是,对于有问题的行,执行后至少1列的值实际上是不同与之前相比。如果你问我这是在这种情况下更改的唯一正确定义。

所以我希望通过检查changes()返回1(行更改)或0(行未更改)后立即调用来检测此类更改执行UPDATE语句。 但令我绝望的是,这似乎没有按预期发挥作用。

请允许我说明一下:

CREATE TABLE People (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL);
INSERT INTO People (Name) VALUES ("Astrid");
SELECT changes();

此处changes()按预期返回1,因为我们只是INSERT第1行。

UPDATE People SET Name = "Emma" WHERE Id = 1;
SELECT changes();

此处changes()按预期返回1,因为1行为UPDATE d(即实际已更改Name Person 1}} Id = 1"Astrid",但现在为"Emma")。

UPDATE People SET Name = "John" WHERE Id = 200;
SELECT changes();

此处changes()按预期返回0,因为没有Id = 200行。

到目前为止一切顺利。但是现在看看下面的UPDATE语句,其中确实与现有行匹配,但 实际上更改它完全(Name仍然设置为"Emma")...

UPDATE People SET Name = "Emma" WHERE Id = 1;
SELECT changes();

此处changes()返回1,而我当然希望0: - (。

如果函数被称为matched_rows()affected_rows(),那么这可能是有意义的。但对于一个名为changes()的函数,并记录在案,这种行为让我觉得不合逻辑,或充其量令人困惑。

所以,无论如何,有人可以解释为什么会发生这种情况,或者甚至更好地提出一种替代策略,以可靠(高效)的方式实现我的目标吗?

我能想到的只是实际执行SELECT * FROM People WHERE Id = x之类的操作,将所有返回的列值与我将要在UPDATE语句中设置的值进行比较,从而决定是否需要执行完全是UPDATE。但这不是很有效,对吧? 当然在这个玩具示例中它可能并不重要,但在我的实际应用程序中,我正在处理具有更多列的表,其中一些列(可能很大)BLOB s。

1 个答案:

答案 0 :(得分:9)

数据库不比较旧值和新值;任何UPDATEd行始终计为"已更改"即使价值恰好相同。 documentation表示

  

UPDATE会影响那些将WHERE子句表达式作为布尔表达式求值的结果为真的行。

如果要检查旧值,则必须明确地执行此操作:

UPDATE People SET Name = 'Emma' WHERE Id = 1 AND Name IS NOT 'Emma';