vérifier l'entrée en double vs utiliser PDO errorInfo résultat

J'ai une table MySQL qui a un champ pour les adresses e-mail qui est défini comme unique. Pour cet exemple, disons que tout ce que mon formulaire fait est de permettre à un utilisateur d'insérer son adresse e-mail dans la table.

Étant donné que le champ email est unique, la requête devrait échouer s'ils essayaient d'entrer le même email deux fois. Je suis curieux de connaître les compromis entre les deux scénarios:

1) exécutez une instruction rapide SELECT avant d'effectuer l'insertion. Si le select renvoie des résultats, informez l'utilisateur et n'exécutez pas l'instruction INSERT.

2) Exécutez l'instruction INSERT et recherchez une erreur d'entrée en double

// snippet uses PDO
if (!$prep->execute($values))
{
    $err = $prep->errorInfo();
    if (isset($err[1]))
    {
        // 1062 - Duplicate entry
        if ($err[1] == 1062)
            echo 'This email already exists.';
    }
}

En outre, veuillez supposer une utilisation normale, ce qui signifie que les entrées en double devraient être minimes. Par conséquent, dans le premier scénario, vous avez évidemment la charge d'exécuter une requête supplémentaire pour chaque insertion , alors que dans la seconde, vous comptez sur la gestion des erreurs.

Aussi, je suis curieux d'entendre des pensées sur le style de codage. Mon cœur me dit " Être un programmeur défensif! Vérifier les données avant de les insérer!"alors que mon cerveau dit" Hmmm, peut-être est-il préférable de laisser MySQL prendre soin de vérifier les données pour vous".

EDIT - Veuillez noter que ce n'est pas une question "Comment puis-je faire cela", mais plutôt une question "Pourquoi devrais-je le faire d'une manière particulière". Le petit extrait de code que j'ai inclus fonctionne, mais ce que je suis curieux est la meilleure façon de résoudre le problème.

28
demandé sur JoshBramlett 2012-05-27 19:05:24

2 réponses

INSERT + vérifier l'état devrait être une meilleure approche. Avec SELECT + INSERT Vous pouvez demander à un autre thread d'insérer la même valeur entre SELECT et INSERT, ce qui signifie que vous devez également envelopper ces deux instructions dans un verrou de table.

Il est facile de se tromper du côté de trop de défense dans votre codage. Python a le dicton que "il est plus facile de demander pardon que de demander la permission", et cette philosophie n'est pas vraiment spécifique à Python.

10
répondu lanzz 2012-05-27 16:10:55

Vous pourriez exécuter ceci avec un bloc try catch:

try {
   $prep->execute($values);
   // do other things if successfully inserted
} catch (PDOException $e) {
   if ($e->errorInfo[1] == 1062) {
      // duplicate entry, do something else
   } else {
      // an error other than duplicate entry occurred
   }
}

Vous pouvez également rechercher des alternatives telles que "INSERT IGNORE" et " INSERT... Sur DUPLICATE KEY UPDATE" - bien que je pense que ceux-ci sont spécifiques à MySQL et irait à l'encontre de la portabilité de L'utilisation de PDO, si c'est quelque chose qui vous préoccupe.

Edit: pour répondre plus formellement à votre question, pour moi, la solution # 1 (le programmeur défensif) en pleine utilisation élimine efficacement le point de la contrainte unique dans le première place. Donc, je suis d'accord avec votre idée de laisser MySQL s'occuper de la vérification des données.

52
répondu Dan LaManna 2012-05-27 16:06:10