Lorsqu'une violation de la contrainte UNIQUE se produit, l'algorithme REPLACE supprime les rangées préexistantes qui sont à l'origine de la violation de la contrainte avant d'insérer ou de mettre à jour la rangée actuelle et la commande continue de s'exécuter normalement. Cela entraîne une modification du rowid et crée le problème suivant
Y:> **sqlite3 test**
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE);**
sqlite> **insert or replace into b values (null,'test-1');**
sqlite> **select last_insert_rowid();**
1
sqlite> **insert or replace into b values (null,'test-2');**
sqlite> **select last_insert_rowid();**
2
sqlite> **insert or replace into b values (null,'test-1');**
sqlite> **select last_insert_rowid();**
3
sqlite> **select * from b;**
2|test-2
3|test-1
La solution consiste à modifier la définition de la colonne c2 comme suit
create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);
et de supprimer la clause "ou remplacer" de vos encarts ;
puis lors du test après votre insertion, vous devrez exécuter le sql suivant : select last_insert_rowid(), changes();
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);**
sqlite> **insert into b values (null,'test-1');**
sqlite> **select last_insert_rowid(), changes();**
1|1
sqlite> **insert into b values (null,'test-2');**
sqlite> **select last_insert_rowid(), changes();**
2|1
sqlite> **insert into b values (null,'test-1');**
sqlite> **select last_insert_rowid(), changes();**
2|0
La valeur de retour des modifications après la troisième insertion sera une notification à votre application que vous devrez rechercher le rowid de "test-1", puisqu'il était déjà dans le fichier. Bien entendu, s'il s'agit d'un système multi-utilisateurs, vous devrez également intégrer tout cela dans une transaction.