PHP PDO MySQL Правильный способ проверить успешность запроса на обновление, если строки не затронуты

Как определить, успешно ли выполнен запрос на обновление при использовании php pdo и mysql?

В моем приложении я обновляю общее количество элементов, отправленных пользователем, и таблица выглядит так:

элементы

userId | itemsAdded | itemsChecked | itemsUnChecked | itemsTotal
     1 |          5 |            2 |              3 |          5

Поэтому, когда я делаю update items set itemTotals = itemsChecked+itemUnChecked, столбец itemsTotal остается прежним, если только не изменяются itemsAdded и не увеличиваются itemsUnChecked (2 + 3 равно 5, 1 + 4 также равно 5).

Раньше я использовал rowCount() для проверки успешности запроса, но в этом случае, поскольку столбец itemsTotal остается прежним, невозможно определить, успешно ли выполнился sql или нет.

$query = $conn->prepare($sql);

$query->execute(array(

    ":itemCount" => $itemCount
    ":itemId" => $itemId
));

$queryCount = $query->rowCount();

if($queryCount == 1) {
    echo 'Updated succeeded';
} else {
    echo 'Updated failed!';
}

Я также мог бы использовать:

$query = $conn->prepare($sql);

$result = $query->execute(array(

    ":itemCount" => $itemCount
    ":itemId" => $itemId
));

if($result) {
    echo 'Updated succeeded';
} else {
    echo 'Updated failed!';
}

Но возвращает ли это значение true или false в зависимости от того, успешно ли выполнился запрос, или в зависимости от количества обновленных строк?

Мне нужно только проверить, был ли запрос успешным или нет. Нет необходимости указывать количество обновленных строк.


person jmenezes    schedule 06.08.2014    source источник
comment
возможный дубликат Как определить, когда запрос успешно выполнен в PHP ПДО?   -  person backtrack    schedule 21.04.2015


Ответы (2)


Метод execute() либо сгенерирует исключение, либо вернет FALSE (в зависимости от режима ошибки, который вы установили для соединения с базой данных), когда выполнение оператора SQL не удается.

Если мы установим режим ошибки для создания исключения перед выполнением оператора (обычно сразу после установления соединения с базой данных), например

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Затем мы можем использовать блок try/catch для обработки исключения, вызванного оператором SQL. Что-то вроде этого:

try {
  $query->execute(...);
  echo 'Update succeeded';

} catch(PDOException $e) {
  echo 'Update failed!';
  echo 'Error: ' . $e->getMessage();
}

Информация о настройках режима ошибок и обработке доступна в документации здесь: http://php.net/manual/en/pdo.error-handling.php


Или, если PDO не настроен на создание исключения, мы можем использовать простой тест if. (Метод execute() вернет FALSE, если оператор завершится ошибкой.)

if ($query->execute(...)) {
   echo 'Update succeeded';

} else {
   echo 'Update failed!';

}

Для более точного управления различными типами сбоев мы можем использовать метод errorCode() для получения SQLSTATE, связанного с последней операцией над дескриптором оператора, и мы можем выполнять условные проверки возвращаемого значения. http://php.net/manual/en/pdostatement.errorcode.php

person spencer7593    schedule 06.08.2014
comment
OK. Таким образом, execute возвращает false, если оператор терпит неудачу, а не в том случае, если строки не обновлялись, верно? - person jmenezes; 06.08.2014
comment
jmenezes: Да, именно так. Успех считается успешным, если инструкция UPDATE выполнена успешно, но обновляет ноль строк. База данных завершила выполнение инструкции и не обнаружила ошибки. (Для оператора UPDATE вполне допустимо воздействовать на нулевые строки, что не считается ошибкой. Либо потому, что ни одна строка не соответствует предикату в предложении WHERE, или потому, что строки не нужно изменять, поскольку существующее значение в столбце уже соответствует значению. в предложении SET.) Вы можете получить то, что вам нужно, из дескриптора оператора, который запустил UPDATE, нет необходимости в другом запросе. - person spencer7593; 06.08.2014
comment
Верно. Спасибо, что объяснили и ответили. - person jmenezes; 06.08.2014
comment
Только после того, как вы определили, что оператор выполнен успешно, вы можете проверить rowCount(), чтобы узнать, сколько строк было затронуто. ПРИМЕЧАНИЕ. Если в соединении PDO::MYSQL_ATTR_FOUND_ROWS => true, то rowCount() возвращает количество найденных (сопоставленных) строк, а не количество затронутых строк. - person spencer7593; 06.08.2014

Даже если никакие строки не затронуты, это не означает, что обновление не удалось, просто, как вы сказали, ничего не изменилось. Это потерпит неудачу только в том случае, если возникнет исключение. Чтобы справиться с этим, вам нужно реализовать блок try/catch.

http://php.net/manual/en/language.exceptions.php

try{
    $query = $conn->prepare($sql);      
    $result = $query->execute(array(    
        ":itemCount" => $itemCount
        ":itemId" => $itemId
    ));
    echo 'Updated succeeded';
} catch(Exception $e) {
    echo 'Updated failed!';
}
person AJ Allen    schedule 06.08.2014
comment
ОК. При проверке второго способа, который я сделал в своем вопросе, возвращает ли выполнение true или false в зависимости от того, был ли запрос выполнен успешно или в зависимости от того, были ли затронуты одна или несколько строк? Как это делается и безопасно ли использовать вместо try catch? - person jmenezes; 06.08.2014
comment
Приведенный выше ответ spencer7593, я думаю, отвечает на ваш вопрос о возвращаемом значении execute. Хорошим способом увидеть, как это произойдет, было бы выполнить оператор обновления в окне командной строки mysql, чтобы увидеть результат. Если вы действительно вносите изменения, должно быть написано: Query Ok, (5) затронутых строк (0,001 с) или, если ни одна не была затронута: Query Ok, (0) затронутых строк (0,001 с). В случае неудачи вы увидите сообщение об ОШИБКЕ. - person AJ Allen; 06.08.2014