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

StackOverflow https://stackoverflow.com/questions/47589

Вопрос

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

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

Для справки: MySQL ПОКАЗАТЬ ПРЕДУПРЕЖДЕНИЯ

Конечно, вы можете обойтись без первоначального запроса 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, чтобы сообщить, какое из них используется.

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

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

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

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

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

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

Предупреждения можно получать более эффективно с помощью 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");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top