我对 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
和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
最佳答案
数据库不比较新旧值;任何 UPDATEd 行总是算作“已更改”,即使值恰好相同。 documentation说
the UPDATE affects … those rows for which the result of evaluating the WHERE clause expression as a boolean expression is true.
如果你想检查旧值,你必须明确地做:
UPDATE People SET Name = 'Emma' WHERE Id = 1 AND Name IS NOT 'Emma';
关于SQLite changes() 计算未更改的更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26372449/