Question

C’est plus une question de correction. Disons que j'ai une table avec une colonne de clé primaire dans ma base de données. Dans mon code DAO, j'ai une fonction appelée insertRow (clé de chaîne) qui renvoie true si la clé n'existe pas dans la table et insère une nouvelle ligne avec la clé. Sinon, si une ligne existe déjà avec cette clé, elle retourne false. Est-il mieux / pire de faire en sorte que insertRow vérifie d’abord l’existence de la clé ou tout simplement de continuer et de procéder à l’insertion et d’attraper la clé dupliquée en erreur? Ou bien économiser sur une seule instruction select est-il une optimisation trop triviale pour que vous puissiez même vous inquiéter?

Donc, dans le code sudo:

boolean insertRow(String key){
    //potentially a select + insert
    if(select count(*) from mytable where key = "somekey" == 0){
       insert into mytable values("somekey")
       return true;
    }
    return false;
}

ou

  boolean insertRow(String key){
    try{
       //always just 1 insert
       insert into mytable values("somekey")
       return true;
    } catch (DuplicateKeyException ex){}
    return false;
  }
Était-ce utile?

La solution

Essayez l'insertion, puis récupérez l'erreur.

Sinon, vous pourriez toujours avoir un problème de concurrence entre deux SPID actifs (disons deux utilisateurs Web sur le système en même temps), auquel cas vous devriez intercepter l'erreur de toute façon:

User1: Check for key "newkey"? Not in database.
User2: Check for key "newkey"? Not in database.
User1: Insert key "newkey". Success.
User2: Insert key "newkey". Duplicate Key Error.

Vous pouvez limiter ce problème en utilisant des transactions explicites ou en définissant le niveau d'isolation de transaction, mais il est simplement plus facile d'utiliser la deuxième technique, à moins que vous ne soyez sûr qu'un seul thread d'application s'exécute en permanence sur la base de données.

Autres conseils

Insérez la ligne, interceptez l'erreur de clé dupliquée. Mon choix personnel

Je pense que cela pourrait mieux fonctionner, en fonction du coût de lancement de l'exception par rapport au coût de frappe de la base de données deux fois.

Ce n'est qu'en testant les deux scénarios que vous saurez à coup sûr

À mon avis, c’est un excellent cas pour utiliser des exceptions (car le doublon est exceptionnel), à moins que vous ne comptiez dessus, la plupart du temps, d’être déjà un rang (c.-à-d. que vous faites " insérer, mais mettre à jour s’il existe " logique.)

Si le but du code est de mettre à jour, vous devez alors utiliser la clause select ou INSERT ... ON DUPLICATE KEY UPDATE (si elle est prise en charge par votre moteur de base de données.) une procédure stockée qui gère cette logique pour vous.

Deuxième parce que la première option frappe deux fois la base de données alors que la deuxième option ne fait l'objet

La réponse courte est que vous devez le tester vous-même. Mon sentiment est que faire un petit choix pour vérifier l'existence fonctionnera mieux, mais vous devez vérifier cela pour vous-même au volume et voir celui qui fonctionne le mieux.

En général, je n'aime pas laisser mon erreur de vérification entièrement au moteur d'exception de ce que je fais. En d'autres termes, si je peux vérifier si ce que je fais est valide plutôt que de simplement avoir une exception levée, c'est généralement ce que je fais.

Je suggérerais toutefois d'utiliser une requête EXISTS plutôt que count (*)

if(exists (select 1 from mytable where key = "somekey"))
    return false
else
    insert the row

Cela étant dit (dans une perspective abstraite et neutre du point de vue du moteur), je suis presque sûr que MySQL contient des mots-clés qui peuvent être utilisés pour insérer une ligne dans une table uniquement si la clé primaire n'existe pas. Cela peut être votre meilleur choix, en supposant que vous puissiez utiliser des mots clés spécifiques à MySQL.

Une autre option serait de placer la logique entièrement dans l'instruction SQL.

deux autres options dans mysql sont à utiliser

insert ignore into....

et

insert into .... on duplicate key update field=value

incluant sur la clé en double mise à jour field = field

Voir: http://dev.mysql.com/doc /refman/5.0/fr/insert.html

Modifier: Vous pouvez tester affects_rows pour savoir si l'insertion a eu un effet ou non.

Maintenant que j'ai trouvé le livre de Martin Fowler en ligne, une solution décente consiste à

scroll top