Cambios SQLite () count ACTUALIZACIONES no cambiantes

Tengo una pregunta sobre la function changes() SQLite, que, de acuerdo con la documentation , " devuelve el número de filas de la database que fueron cambiadas o insertadas o eliminadas por la instrucción INSERT, DELETE o UPDATE completada más recientemente " (también vea la documentation de la function C / C ++ subyacente ).

Esperaba usar esta function para verificar si la ejecución de una instrucción UPDATE perteneciente a una sola fila realmente ha causado que esa fila sea modificada o no. Por cambio no solo quiero decir que la fila coincide con la cláusula WHERE la statement. No, en cambio, lo que quiero decir es que, para la fila en cuestión, el valor de al less 1 columna es realmente diferente después de la ejecución en comparación con el anterior. Si me preguntas, esta es la única definición adecuada de cambio en este context.

Así que esperaba detectar dichos cambios comprobando si changes() devuelve 1 (fila cambiada) o 0 (fila sin cambios) cuando se llama justo después de la ejecución de la instrucción UPDATE . Pero para mi desesperación, esto no parece funcionar como se esperaba.

Permítame ilustrar:

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

Aquí changes() devuelve 1 , como se esperaba porque simplemente INSERT ed 1 fila.

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

Aquí changes() devuelve 1 , como se esperaba, porque 1 fila era UPDATE d (es decir, realmente cambiada : el Name de la Person con Id = 1 era "Astrid" pero ahora es "Emma" ).

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

Aquí changes() devuelve 0 , como se esperaba porque no hay fila con Id = 200 .

Hasta aquí todo bien. Pero ahora eche un vistazo a la siguiente instrucción UPDATE , que de hecho coincide con una fila existente, pero en realidad no la cambia en absoluto ( Name permanece establecido en "Emma" ) …

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

Aquí changes() devuelve 1 , mientras que por supuesto esperaba 0 :-(.

Quizás esto hubiera tenido sentido si la function se llamaba algo así como matched_rows() o affected_rows() . Pero para una function llamada changes() , y documentada tal como está, este comportamiento me parece ilógico, o confuso en el mejor de los casos.

Entonces, de todos modos, ¿alguien puede explicar por qué sucede esto o, mejor aún, sugerir una estrategia alternativa para lograr mi objective de una manera confiable (y eficiente)?

Todo lo que puedo pensar es hacer algo como SELECT * FROM People WHERE Id = x , comparar todos los valores devueltos de la columna con los valores que estoy a punto de configurar en la instrucción UPDATE y decidir si necesito ejecutar UPDATE en absoluto . Pero eso no puede ser muy eficiente, ¿verdad? Por supuesto, en este ejemplo de juguete podría no importar mucho, pero en mi aplicación real estoy tratando con tablas con muchas más columnas, algunas de las cuales son (potencialmente grandes) BLOB .

La database no compara valores antiguos y nuevos; cualquier fila ACTUALIZADA siempre count como "modificada" incluso si los valores son los mismos. La documentation dice que

la ACTUALIZACIÓN afecta … a aquellas filas para las cuales el resultado de evaluar la expresión de la cláusula WHERE como una expresión booleana es verdadera.

Si desea verificar el valor anterior, debe hacerlo explícitamente:

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