Могу ли я обнаруживать и обрабатывать предупреждения MySQL с помощью PHP?

Я имею дело с таблицей MySQL, которая определяет столбец JobName как UNIQUE. Если кто-то пытается сохранить новое задание в базе данных с помощью JobName, которое уже находится в базе данных, MySQL выдает предупреждение.

Я хотел бы иметь возможность обнаружить это предупреждение, как ошибку, в моем PHP-скрипте и справиться с ним соответствующим образом. В идеале я хотел бы знать, какое предупреждение вышло MySQL, чтобы я мог развернуть код для его обработки.

Это возможно? Если нет, это потому, что MySQL не обладает этой способностью, PHP не обладает этой способностью или и то, и другое?

Для того, чтобы предупреждения были «помечены» для PHP, изначально потребовались бы изменения в драйвере mysql / mysqli, что явно выходит за рамки этого вопроса. Вместо этого вам придется в основном проверить каждый запрос, который вы делаете в базе данных, на наличие предупреждений:

$warningCountResult = mysql_query("SELECT @@warning_count"); if ($warningCountResult) { $warningCount = mysql_fetch_row($warningCountResult ); if ($warningCount[0] > 0) { //Have warnings $warningDetailResult = mysql_query("SHOW WARNINGS"); if ($warningDetailResult ) { while ($warning = mysql_fetch_assoc(warningDetailResult) { //Process it } } }//Else no warnings } 

Очевидно, что это будет ужасно дорого для применения en-mass, поэтому вам может потребоваться внимательно подумать о том, когда и как могут возникнуть предупреждения (что может привести к реорганизации для их устранения).

Для справки, MySQL SHOW WARNINGS

Конечно, вы можете отказаться от первоначального запроса для SELECT @@warning_count , который сохранит вам запрос за выполнение, но я включил его для полноты педантичности.

Во-первых, вы должны отключить предупреждения, чтобы ваши посетители не видели ваши ошибки MySQL . Во-вторых, когда вы вызываете mysql_query() , вы должны проверить, вернул ли он false. Если это так, вызовите mysql_errno() чтобы узнать, что пошло не так. Сопоставьте номер, возвращенный кодам ошибок на этой странице .

Похоже, это номер ошибки, которую вы ищете:

Ошибка: 1169 SQLSTATE: 23000 (ER_DUP_UNIQUE)

Сообщение: не удается записать из-за уникального ограничения в таблицу '% s'

 ini_set('mysql.trace_mode', 1) 

может быть то, что вы ищете.

Затем ошибки PHP можно обрабатывать с помощью специального обработчика ошибок PHP, но вы также можете просто отключить отображение ошибок php, поскольку они обычно регистрируются в файле журнала (в зависимости от вашей конфигурации php).

в зависимости от того, какую структуру (если есть) вы используете, я предлагаю вам выполнить запрос, чтобы проверить имя задания самостоятельно и создать правильную информацию для пользователя с остальной частью валидации для формы.

В зависимости от количества рабочих имен вы можете отправить имена в представление, которое содержит форму, и использовать javascript, чтобы сообщить об использовании, которое было принято.

Если это не имеет смысла для вас, то, чтобы суммировать мое мнение, это так: не создавайте свою программу и / или пользователей, чтобы пытаться делать незаконные вещи и ловить ошибки, когда они это делают и обрабатывают. Намного лучше, imho, создать вашу систему, чтобы не создавать ошибок. Храните ошибки в реальных ошибках 🙂

Обновлено, чтобы удалить информацию о функциях errno, которые я теперь понимаю, не применяются в вашей ситуации …

Одна вещь в MySQL, которую следует опасаться для операторов UPDATE : mysqli_affected_rows() будет возвращать ноль, даже если строки WHERE , согласованные с строками, но предложение SET фактически не изменяло значения данных. Я упоминаю об этом только потому, что это поведение вызвало ошибку в системе, которую я когда-то смотрел – программист использовал это возвращаемое значение для проверки ошибок после обновления, предполагая, что нуль означает, что произошла какая-то ошибка. Это просто означало, что пользователь не изменил никаких существующих значений перед нажатием кнопки обновления.

Поэтому я полагаю, что использование mysqli_affected_rows() не может быть основано на обнаружении таких предупреждений, если только у вас есть что-то вроде столбца update_time в вашей таблице, которому при обновлении всегда будет присвоено новое значение временной метки. Однако такое обходное решение кажется любезным kludgey.

Вы можете обнаружить уникальные нарушения, используя ошибку mysqli. Оператор mysqli возвращает ошибку 1062, то есть ER_DUP_ENTRY. Вы можете найти ошибку 1062 и напечатать подходящее сообщение об ошибке. Если вы хотите распечатать свой столбец (имя_пользователя) также как часть сообщения об ошибке, вы должны проанализировать строку ошибки оператора.

   if ($ stmt = $ mysqli-> prepare ($ sql)) {
             $ Stmt-> bind_param ( "SSS",
             $ Имя,
             $ IdentKey,
             $ Домена);


             $ Stmt-> Execute ();
             if ($ mysqli-> affected_rows! = 1) {
                         // Это вернет errno 1062
                 trigger_error ('mysql error >>'. $ stmt-> errno. '::'. $ stmt-> error, E_USER_ERROR);
                 выход (1);
             }
             $ Stmt-> близко ();
         } else {

             trigger_error ('mysql error >>'. $ mysqli-> errno. '::'. $ mysqli-> error, E_USER_ERROR);
         }

Можно получить предупреждения и более эффективно с mysqli, чем с mysql.

Вот код, предложенный на странице руководства на php.net для свойства mysqli-> warning_count:

 $mysqli->query($query); if ($mysqli->warning_count) { if ($result = $mysqli->query("SHOW WARNINGS")) { $row = $result->fetch_row(); printf("%s (%d): %s\n", $row[0], $row[1], $row[2]); $result->close(); } } 

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

Пример:

  // this suppresses warnings that might result if there is no field titled "field" in the result $field_value = @mysql_result($result, 0, "field");