Подтвердить что ты не робот

Проверить дублируемую запись и использовать результат PDO errorInfo

У меня есть таблица MySQL, в которой есть поле для адресов электронной почты, которое определено как уникальное. В этом примере предположим, что вся моя форма позволяет пользователю вставлять свой адрес электронной почты в таблицу.

Поскольку поле электронной почты уникально, запрос должен быть неудачным, если он пытается дважды ввести один и тот же адрес электронной почты. Мне любопытно компромисс между двумя сценариями:

1) Запустите быстрый SELECT оператор перед выполнением вставки. Если выбор возвращает результаты, сообщите об этом пользователю и не запускайте оператор INSERT.

2) Запустите оператор INSERT и проверьте наличие повторяющейся ошибки записи

// 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.';
    }
}

Кроме того, предположите, что это нормальное использование, что означает, что дублирующие записи должны быть минимальными. Поэтому в первом сценарии у вас, очевидно, есть накладные расходы на выполнение дополнительного запроса для каждой вставки, тогда как во втором вы полагаетесь на обработку ошибок.

Кроме того, мне любопытно слышать мысли о стиле кодирования. Мое сердце говорит: "Будь защитником! Проверьте данные перед вставкой! ' в то время как мой мозг говорит:" Хм, может быть, лучше позволить MySQL позаботиться о проверке данных для вас".

РЕДАКТИРОВАТЬ. Обратите внимание, что это не вопрос "Как это сделать", а вопрос "Почему я должен делать это конкретным образом". Небольшой фрагмент кода, который я включил в работу, но то, что мне интересно, - лучший способ решить проблему.

4b9b3361

Ответ 1

INSERT + статус проверки должен быть лучшим подходом. С помощью SELECT + INSERT у вас может быть другой поток, вставляющий одно и то же значение между SELECT и INSERT, что означает, что вам нужно будет также обернуть эти два оператора в блокировку таблицы.

Легко ошибиться на стороне слишком большой защиты в вашей кодировке. У Python есть высказывание, что "легче просить прощения, чем запрашивать разрешение", и эта философия не является специфичной для Python.

Ответ 2

Вы можете выполнить это с помощью блока catch try:

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
   }
}

Вы также можете изучить альтернативы, такие как "INSERT IGNORE" и "INSERT... ON DUPLICATE KEY UPDATE" - хотя я думаю, что они специфичны для MySQL и будут противоречить переносимости использования PDO, если это то, беспокоиться.

Изменить: Чтобы более формально ответить на ваш вопрос, для меня решение № 1 (защитный программист) в полном объеме эффективно устраняет точку единственного ограничения в первую очередь. Поэтому я бы согласился с вашей мыслью позволить MySQL позаботиться о проверке данных.