Обнаружение ошибки по сравнению с незатронутой строкой с помощью PHP PDO rowCount()

Используя PHP PDO, есть ли способ различить разницу между сбоем UPDATE и успешно запущенным UPDATE, но установившим для поля его существующее значение?

$sql = 'UPDATE table SET column = :column WHERE id = :id';
$statement = $db->prepare($sql);
$statement->bindParam(':column', $column, PDO::PARAM_STR);
$statement->bindParam(':id', $id, PDO::PARAM_INT);
$statement->execute();
$RowsUpdated = $statement->rowCount();
echo '$RowsUpdated = '.$RowsUpdated.'<br />';

Приведенный выше код устанавливает $RowsUpdated в 1, если значение $column является новым значением, и устанавливает его в 0, если оно совпадает с существующим значением. Я попытался вызвать ошибку, изменив оператор SQL, но он никогда не возвращает нечисловое значение (например, NULL или False) и никогда не меньше 0.

Когда SELECT'ирует строки с помощью COUNT(*), fetchColumn() возвращает количество строк, если они есть, или 0, если их нет, или что-то еще, если есть ошибка. Таким образом, я могу использовать ($countRowsSelected > 0) для обнаружения строк, ($countRowsSelected === "0") для обнаружения отсутствия строк и ELSE для обнаружения ошибки.

Можно ли это сделать с помощью ОБНОВЛЕНИЯ? В дополнение к ОБНОВЛЕНИЮ я хочу инициировать вторичные действия, но только если сохраненное значение ИЗМЕНЕНО, поэтому я хочу этого:

if ($RowsUpdated > 0) {
    // We go a NEW value, let's do a little dance
} else if ($RowsUpdated === "0") {
    // It saved, but the value was unchanged
} else {
    // Error!
}

Я попытался добавить PDO::MYSQL_ATTR_FOUND_ROWS => true к моему PDO, но это заставило rowCount() возвращать 1 независимо от того, изменилось ли значение, поэтому это не помогло.


person Ed Williams    schedule 28.01.2013    source источник
comment
неудавшийся оператор вернет логическое значение false или вызовет исключение, в зависимости от ваших настроек pdo. запрос, который ничего не обновляет (или не сопоставляет), не является ошибкой - это просто пустой набор результатов.   -  person Marc B    schedule 28.01.2013
comment
ОБНОВЛЕНИЕ не удалось, возможно, вы должны использовать транзакции ACID - с помощью try catch вы можете проверить, когда он терпит неудачу.   -  person Ragen Dazs    schedule 28.01.2013
comment
Я использовал ERRMODE_SILENT, который, по моему мнению, был лучшим/наиболее безопасным для живых сред, но я предполагаю, что это, возможно, подавляло ошибку (?), Хотя я все еще мог получить 1, 0 или NULL из SELECT с этим параметром, но не с обновление. Было бы полезно знать, где ошибка, а не просто ловить ошибку где-то в PDO. Это означает, что было бы хорошо определить, что ошибка связана с ОБНОВЛЕНИЕМ, возвращая 1+, 0 или NULL для строк ОБНОВЛЕНО.   -  person Ed Williams    schedule 28.01.2013


Ответы (1)


Вы можете сделать одно из следующих действий:

  1. Используйте PDO::errCode(), соответственно PDOStatement::errorCode(), чтобы проверить, не произошла ли ошибка SQL, или
  2. Инициализируйте соединение с базой данных, установив для параметра PDO::ATTR_ERRMODE значение PDO::ERRMODE_EXCEPTION (см. руководство). Таким образом, PDO выдает исключение, которое вы можете перехватить.
person helmbert    schedule 28.01.2013
comment
Вы предпочитаете один из этих подходов другому? Я думаю, ERRMODE_EXCEPTION может быть выходом. Безопасно ли использовать в живых средах, если я вывожу только пользовательское сообщение (а не $e->getMessage() PDOException)? Похоже, что try/catch обнаружит любую ошибку внутри PDO, будь то в начальном SELECT или последующем UPDATE, поэтому я думаю, что он будет учитывать ЛЮБУЮ ошибку вплоть до финального '$db = null;' утверждение. Если это так, мне не нужна отдельная ошибка для ОБНОВЛЕНИЯ, достаточно одной общей ошибки для любого сбоя, и это здорово. Вы можете это подтвердить? - person Ed Williams; 28.01.2013
comment
Я предпочитаю ERRMODE_EXCEPTION. Проверку ошибок с помощью errorCode() после каждого запроса легко забыть (делать ошибки, которые вы забыли проверить, еще более удивительно). На мой взгляд, использование исключений облегчает отслеживание ошибок. Использование этого подхода в реальной среде обычно не представляет проблемы, поскольку вы можете перехватить исключение и обработать его по своему усмотрению (например, распечатать его вместе со стеком вызовов в вашей среде разработки и просто вывести общее сообщение об ошибке в вашей рабочей среде). окружающая обстановка). - person helmbert; 29.01.2013