Это хороший случай для использования транзакции?

0

У меня есть следующее update of the users table и selection который дает мне updated result сразу после обновления, и мне интересно, если уместно использовать transaction здесь? Кроме того, если да, то я использую его правильно в codewisely together with prepared statements?

try {

        // connect to the database
        require 'connect.php';
        // create an update query
        $conn->beginTransaction();
        $queryUpdate = $conn->prepare("UPDATE users SET userName=:userName, firstName=:firstName,
        lastName=:lastName, password=:password, image=:image  WHERE userId=:userId"); 
        $queryUpdate->bindParam( ':userId' , $sUserId );
        $queryUpdate->bindParam( ':userName' , $sNewUserName );
        $queryUpdate->bindParam( ':firstName' , $sNewFirstName );
        $queryUpdate->bindParam( ':lastName' , $sNewLastName );
        $queryUpdate->bindParam( ':password' , $sNewPassword );
        $queryUpdate->bindParam( ':image' , $sNewImagePath );
        $bResult = $queryUpdate->execute();
        // create another query to get some of the updated values
        $querySelect = $conn->prepare("SELECT users.userName, users.firstName, users.lastName, users.image
        FROM users WHERE userId=:userId");
        $querySelect->bindParam( ':userId' , $sUserId );
        // run query 
        $querySelect->execute();  
        $ajResult = $querySelect->fetch(PDO::FETCH_ASSOC);
        // take each property one by one
        $sUserName = $ajResult['userName'];
        $sFirstName = $ajResult['firstName'];
        $sLastName = $ajResult['lastName'];
        $sImagePath = $ajResult['image'];
        // i.e. no query has failed, and we can commit the transaction
        $conn->commit();
        $sjResponse = $bResult ? '{"status":"ok", "userName":"'.$sUserName.'", "firstName":"'.$sFirstName.'",
         "lastName":"'.$sLastName.'", "image":"'.$sImagePath.'"}' : '{"status":"error"}'; 
        echo $sjResponse;
} catch (Exception $e) {
        // An exception has been thrown
        // We must rollback the transaction
        echo "ERROR";
        $conn->rollback();

}
  • 0
    Действительно не уверены, почему после обновления записи вы выбираете обратно те же данные. Ожидаете ли вы обновления не получится или кто-то другой обновит его?
  • 0
    Потому что мне нужно отправить результат в интерфейс.
Теги:
transactions
prepared-statement

2 ответа

1
Лучший ответ

Если вам просто нужно передать результат обновления, если выполнение обновления преуспело, то передайте обратно значения, которые вы только что использовали в обновлении. В качестве дополнительной проверки вы можете использовать rowCount() чтобы проверить, что она действительно что-то обновила.

require 'connect.php';
// create an update query
$queryUpdate = $conn->prepare("UPDATE users SET userName=:userName, firstName=:firstName,
lastName=:lastName, password=:password, image=:image  WHERE userId=:userId"); 
$queryUpdate->bindParam( ':userId' , $sUserId );
$queryUpdate->bindParam( ':userName' , $sNewUserName );
$queryUpdate->bindParam( ':firstName' , $sNewFirstName );
$queryUpdate->bindParam( ':lastName' , $sNewLastName );
$queryUpdate->bindParam( ':password' , $sNewPassword );
$queryUpdate->bindParam( ':image' , $sNewImagePath );
$bResult = $queryUpdate->execute();
$sjResponse = ( $bResult && $queryUpdate->rowCount() == 1) ? 
   '{"status":"ok",
    "userName":"'.$sUserName.'", 
    "firstName":"'.$sNewFirstName.'",
    "lastName":"'.$sNewLastName.'", 
    "image":"'.$sNewImagePath.'"}' 
  : '{"status":"error"}'; 
echo $sjResponse;

Что касается транзакций - они более актуальны, когда вы делаете несколько обновлений/вставки/удаления в базу данных. Например, если вы хотите перенести некоторые точки от одного пользователя к другому - вы хотите убедиться, что значение, снятое с пользователя A, попадает пользователю B. Если вы вычтите значение из A, а затем что-то не удалось с обновлением пользователя B, тогда точки могут просто исчезнуть. Используя транзакции, это может отменить оба изменения, и все согласовано.

  • 0
    Я использую PDO, так что эквивалентно mysqli->affected_rows ?
  • 0
    Извинения - я должен был понять из bindParams, использовать rowCount() в заявлении (обновленный код)
0

Мне интересно, если уместно использовать транзакцию здесь?

IMO, Нет. У вас есть только одно выражение об обновлении для управления таблицей.

Таким образом, цель объединения нескольких SQL в единую транзакцию также является типом логической группировки всех связанных SQL, и они должны выполняться в одной последовательности. И вы сможете использовать некоторые другие функции, такие как SAVEPOINT, ROLLBACK и COMMIT хотя некоторые из них могут использоваться при выполнении простого запроса (без транзакции).

Я бы предложил прочитать Transactional and Locking Statement

Ещё вопросы

Сообщество Overcoder
Наверх
Меню