Могу ли я обнаружить и обработать предупреждения MySQL с помощью PHP? - PullRequest
11 голосов
/ 06 сентября 2008

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

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

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

Ответы [ 8 ]

10 голосов
/ 06 сентября 2008

Для того чтобы предупреждения были «помечены» в 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 ПОКАЗАТЬ ПРЕДУПРЕЖДЕНИЯ

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

4 голосов
/ 06 сентября 2008

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

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

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

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

3 голосов
/ 07 ноября 2011
ini_set('mysql.trace_mode', 1)

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

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

0 голосов
/ 20 февраля 2011

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

Пример:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");
0 голосов
/ 08 января 2010

С помощью 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();
    }
}
0 голосов
/ 30 мая 2009

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

  if($stmt = $mysqli->prepare($sql)){
            $stmt->bind_param("sss",
            $name,
            $identKey,
            $domain);


            $stmt->execute();
            if($mysqli->affected_rows != 1)  {
                        //This will return errorno 1062
                trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR);
                exit(1);
            }
            $stmt->close();
        } else {

            trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR);
        }
0 голосов
/ 06 сентября 2008

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

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

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

0 голосов
/ 06 сентября 2008

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

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

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

...