Question

J'ai une liste de chaînes à insérer dans une base de données. Ils doivent être uniques. Lorsque j'insère, je souhaite que leur identifiant (à utiliser comme clé étrangère dans une autre table) afin que j'utilise last_insert_rowid. J'ai 2 problèmes.

  1. Si j'utilise replace, leur identifiant (INTEGER PRIMARY KEY) mises à jour qui casse ma db (les entrées pointent vers identifiants inexistants)
  2. Si j'utilise ignore, rowid n'est pas mis à jour, je ne reçois donc pas le bon identifiant

Comment puis-je obtenir leurs identifiants? si je n'en ai pas besoin, je ne voudrais pas utiliser une instruction select pour vérifier et insérer la chaîne si elle n'existe pas. Comment dois-je faire cela?

Était-ce utile?

La solution 2

J'utilise actuellement le ci-dessous

insert into tbl(c_name) select 'val' where not exists(select id from tbl where c_name ='val');
select id from tbl where c_name ='val';

Autres conseils

Lorsqu'une violation de contrainte UNIQUE se produit, l'algorithme REPLACE supprime les lignes préexistantes à l'origine de la violation de contrainte avant l'insertion ou la mise à jour de la ligne actuelle et la commande continue de s'exécuter normalement. Cela provoque le rowid pour changer 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 supprimer le " ou remplacer " clause de vos insertions;

puis lorsque testez après votre insertion, vous devrez exécuter le code 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 3ème insertion sera une notification à votre application que vous aurez besoin de rechercher le rowid de & "test-1 &"; étant donné qu'il figurait déjà dans le fichier. Bien sûr, s’il s’agit d’un système multi-utilisateurs, vous devrez également envelopper tout cela dans une transaction.

Par & "ils DOIVENT être uniques &", signifient-ils que vous êtes sûr qu'ils le sont ou que vous voulez une erreur s'ils ne le sont pas? Si vous ne faites que la chaîne elle-même une clé dans sa table, alors je ne comprends pas pourquoi 1 ou 2 pourraient être un problème - vous obtiendrez une erreur si vous le souhaitez en cas de duplication non souhaitée, sinon l'identifiant correct. Peut-être pouvez-vous clarifier votre question avec un petit exemple du code SQL que vous utilisez, la table en question, quel comportement observez-vous et quel comportement souhaitez-vous plutôt ...?

Modifié: merci pour la modification, mais je ne vois toujours pas ce que SQL vous pose quels problèmes! Si votre table provient de, par exemple:

CREATE TABLE Foo(
  theid INTEGER PRIMARY KEY AUTOINCREMENT,
  aword TEXT UNIQUE ABORT
  )

toute tentative d'insérer un mot dupliqué échouera (le mot clé ABORT est facultatif, car il s'agit du paramètre par défaut pour UNIQUE). N'est-ce pas ce que vous voulez étant donné que vous prononcez les mots & "DOIT être unique &", c’est-à-dire qu’il s’agit d’une erreur s’ils ne le sont pas?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top