2017-08-20 4 views
0

J'ai une requête simpe comme ceci:MySQL: Insérez plusieurs valeurs si elles n'existent pas, mais ont besoin d'un contrôle plusieurs colonnes

INSERT INTO myTable (col1, col2) VALUES 
    (1,2), 
    (1,3), 
    (2,2) 

je dois faire une vérification qu'aucune valeur en double ont été ajoutés, mais la vérification doit se produire dans les deux colonnes: si une valeur existe dans col1 et col2 alors je ne veux pas insérer. Si la valeur existe seulement dans l'une de ces colonnes mais pas les deux, puis insérez devrait passer par ..

En d'autres termes, disons que nous avons le tableau suivant:

+-------------------------+ 
|____col1____|___col2_____| 
|  1  |  2  | 
|  1  |  3  | 
|______2_____|_____2______| 

valeurs Insertion comme (2,3) et (1,1) serait être autorisé, mais (1,3) ne serait pas autorisé.

Est-il possible de faire un WHERE NOT EXISTS vérifier une seule fois? Il se peut que j'aie besoin d'insérer 1000 valeurs à la fois et je ne suis pas sûr que faire un WHERE vérifier sur chaque ligne d'insertion serait efficace. Pour ajouter à la question - s'il y a une valeur dupliquée sur les deux colonnes, j'aimerais que la requête ignore cette ligne spécifique et continue à insérer d'autres valeurs plutôt que de lancer une erreur.

Répondre

2

Ce que vous pouvez utiliser est une clé primaire ou un index unique dans ces colonnes. Ensuite, vous pouvez utiliser replace into ou tout simplement insert ignore:

create table myTable 
(
    a int, 
    b int, 
    primary key (a,b) 
); 

-- Variant 1 
replace into myTable(a,b) values (1, 2); 

-- Variant 2 
insert ignore into myTable(a,b) values (1,2); 

Voir Insert Ignore et Replace Into

En utilisant cette dernière variante a l'avantage que vous ne modifiez aucun enregistrement si elle existe déjà (donc pas besoin de reconstruire un index) et correspondrait le mieux à vos besoins concernant votre question.

Si, toutefois, d'autres colonnes doivent être mises à jour lors de l'insertion d'un enregistrement ne respectant pas une contrainte unique, vous pouvez utiliser replace into ou insert into ... on duplicate key update.

Replace into effectuera une véritable suppression avant d'insérer un nouveau record, alors que insert into ... on duplicate key update effectuera une mise à jour à la place. Bien que l'on pourrait penser que le résultat sera le même, alors pourquoi est-il une déclaration pour les deux opérations, la réponse se trouve dans les effets secondaires:

Replace into supprimera l'ancien record avant d'insérer le nouveau. Cela provoque la mise à jour de l'index, la suppression et l'insertion des déclencheurs (si définis) et, surtout, si vous avez une contrainte de clé étrangère (avec on delete restrict ou on delete cascade), votre contrainte se comportera exactement de la même manière que si vous supprimé l'enregistrement manuellement et inséré la nouvelle version plus tard. Cela signifie: Soit votre opération échoue parce que la restriction est en place, soit l'opération de suppression est mise en cascade sur la table cible (c'est-à-dire la suppression des enregistrements connexes, bien que vous ayez simplement modifié certaines données de colonne).

D'autre part, lors de l'utilisation on duplicate key update, déclencheurs de mise à jour se faire virer, les index sur les colonnes modifiées seront réécrite une fois, si une clé étrangère est définie on update cascade pour l'une des colonnes en cours de modification, cette opération est réalisée comme bien.

Pour répondre à votre question dans les commentaires, comme indiqué dans le manuel:

Si vous utilisez le modificateur IGNORE, les erreurs qui se produisent lors de l'exécution de l'instruction INSERT sont ignorées. Par exemple, sans IGNORE, une ligne qui duplique un index UNIQUE existant ou une valeur PRIMARY KEY dans la table provoque une erreur de clé dupliquée et l'instruction est abandonnée. Avec IGNORE, la ligne est ignorée et aucune erreur ne se produit. Les erreurs ignorées peuvent générer des avertissements à la place, bien que les erreurs de clé dupliquée ne le soient pas.

Ainsi, toutes les violations sont traités comme des avertissements plutôt que erreurs, ce qui provoque l'insert pour terminer. Sinon, l'insertion sera appliquée partiellement (sauf lors de l'utilisation de transactions). Les violations de duplicate key, cependant, ne produisent même pas un tel avertissement. Néanmoins, tous les enregistrements ne respectant aucune contrainte ne seront pas insérés du tout, mais ignore garantira que tous les enregistrements valides seront insérés (étant donné qu'il n'y a pas de défaillance du système ou de manque de mémoire).

+0

Merci pour cela. Juste une question - si j'utilise Insérer Ignorer, ce sera un ignorant global? c'est-à-dire - va-t-il supprimer seulement les erreurs s'il y a une entrée en double sur ces deux colonnes? Que faire s'il y a une valeur invalide dans la requête - l'erreur sera-t-elle supprimée? Je voudrais que la requête supprime seulement les erreurs pour les valeurs dupliquées sur ces deux colonnes, mais qu'elle aimerait quand même lancer d'autres erreurs si elles se produisent. – user1775598

+0

Je vais mettre à jour la réponse en fonction de cette question – Psi