INSERT IF NOT EXIST ELSE UPDATE?
j'en ai trouvé quelques-unes" serait "des solutions pour le classique" Comment puis-je insérer un nouvel enregistrement ou en mettre un à jour s'il existe déjà " mais je ne peux pas en faire fonctionner un seul en SQLite.
j'ai un tableau défini comme suit:
CREATE TABLE Book
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name VARCHAR(60) UNIQUE,
TypeID INTEGER,
Level INTEGER,
Seen INTEGER
ce que je veux faire, c'est ajouter un enregistrement avec un nom unique. Si le Nom existe déjà, je veux modifier les champs.
est-ce que quelqu'un peut me dire comment faire s'il vous plaît?
8 réponses
regardez http://sqlite.org/lang_conflict.html .
Vous voulez quelque chose comme:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values
((select ID from Book where Name = "SearchName"), "SearchName", ...);
notez que tout champ ne figurant pas dans la liste insert sera défini à NULL si la ligne existe déjà dans la table. C'est la raison pour laquelle il y a un sous-Select pour la colonne ID
: dans le cas de remplacement, la déclaration serait définie à NULL et alors un nouvel ID serait attribué.
cette approche peut aussi être utilisé si vous voulez laisser des valeurs de champ particulières seules si la ligne dans le cas de remplacement mais mettez le champ à NULL dans le cas d'insertion.
par exemple, en supposant que vous voulez laisser Seen
seul:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values (
(select ID from Book where Name = "SearchName"),
"SearchName",
5,
6,
(select Seen from Book where Name = "SearchName"));
vous devez utiliser la commande INSERT OR IGNORE
suivie de la commande UPDATE
:
Dans l'exemple suivant name
est une clé primaire:
INSERT OR IGNORE INTO my_table (name, age) VALUES ('Karen', 34)
UPDATE my_table SET age = 34 WHERE name='Karen'
la première commande insérera l'enregistrement. Si l'enregistrement existe, il ignore l'erreur provoquée par le conflit avec une clé primaire.
la deuxième commande mettra à jour l'enregistrement (qui existe maintenant définitivement)
vous devez définir une contrainte sur la table pour déclencher un " conflit "que vous résolvez ensuite en faisant un remplacement:
CREATE TABLE data (id INTEGER PRIMARY KEY, event_id INTEGER, track_id INTEGER, value REAL);
CREATE UNIQUE INDEX data_idx ON data(event_id, track_id);
alors vous pouvez émettre:
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 2, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 5);
le "SELECT * FROM data" vous donnera:
2|2|2|3.0
3|1|2|5.0
notez que les données.id est " 3 "et non" 1 " parce que remplacer fait un Supprimer et insérer, pas une mise à jour. Cela signifie également que vous devez vous assurer que vous définissez tous les colonnes nécessaires ou vous obtiendrez des valeurs nulles inattendues.
tout d'abord mettre à jour. Si nombre de lignes affectées = 0, alors insérez-le. C'est le plus facile et adapté pour tous RDBMS .
INSERT OR REPLACE
remplacera les autres champs ( TypeID
, Level
) par la valeur par défaut.
INSERT OR REPLACE INTO book(id, name) VALUES(1001, 'Programming')
j'utilise ce
INSERT OR IGNORE INTO book(id) VALUES(1001);
UPDATE book SET name = 'Programming' WHERE id = 1001;
vous pouvez également utiliser
INSERT OR REPLACE INTO book (id, name)
VALUES (1001, 'Programming',
(SELECT typeid FROM book WHERE id = 1001),
(SELECT level FROM book WHERE id = 1001),
)
mais je pense que la première méthode plus facile à lire
Si vous n'avez pas de clé primaire, Vous pouvez insérer s'il n'existe pas, puis faire une mise à jour. Le tableau doit contenir au moins une entrée avant de l'utiliser.
INSERT INTO Test
(id, name)
SELECT
101 as id,
'Bob' as name
FROM Test
WHERE NOT EXISTS(SELECT * FROM Test WHERE id = 101 and name = 'Bob') LIMIT 1;
Update Test SET id='101' WHERE name='Bob';
je crois que vous voulez UPSERT .
"insérer ou remplacer" sans la supercherie supplémentaire dans cette réponse va réinitialiser tous les champs que vous ne spécifiez pas à NULL ou autre valeur par défaut. (Ce comportement D'INSERT ou de REPLACE est différent de UPDATE; il est exactement comme INSERT, car il est en fait INSERT; cependant si ce que vous vouliez est UPDATE-if-exists vous voulez probablement la sémantique de mise à jour et sera désagréablement surpris par le résultat réel.)
la ruse de L'implémentation upsert suggérée est essentiellement D'utiliser insérer ou remplacer, mais de spécifier tous les champs, en utilisant des clauses de sélection intégrées pour récupérer la valeur courante pour les champs que vous ne voulez pas changer.
je pense qu'il vaut la peine de souligner qu'il peut y avoir un comportement inattendu ici si vous ne comprenez pas bien comment clé primaire et UNIQUE interagir.
à titre d'exemple, si vous voulez insérer un enregistrement seulement si le champ nom n'est pas pris actuellement, et si c'est le cas, vous voulez qu'une exception de contrainte s'allume pour vous le dire, alors insérer ou remplacer ne lancera pas et exception et résoudra la contrainte UNIQUE en remplaçant le document en conflit (le document existant par le même nom ). Gaspard démontre très bien dans sa réponse ci-dessus.
si vous voulez une exception de contrainte au feu, vous devez utiliser un INSERT statement, et compter sur une mise à jour séparée commande pour mettre à jour le dossier une fois que vous savez que le nom n'est pas pris.