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

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

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

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

8 ответов

Решение

Для того, чтобы предупреждения были "помечены" в 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
}

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

Для справки, 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).

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

  if ($ stmt = $ mysqli-> prepare ($ sql)) {$ stmt-> bind_param ("sss", $ name, $ identKey, $ domain); $ Stmt-> Execute();
            if($mysqli-> disabled_rows!= 1)  {
                        // Это вернет errorno 1062
                trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR); выход (1);
            }
            $stmt->close();
        } else {

            trigger_error('ошибка mysql >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR);
        }

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

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

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

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

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

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

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

Пример:

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

С помощью 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();
    }
}
Другие вопросы по тегам