Практическое руководство. Выполнение транзакций
Драйвер SQLSRV драйверов Майкрософт для PHP для SQL Server предоставляет три функции для выполнения транзакций:
Драйвер PDO_SQLSRV предоставляет три метода для выполнения транзакций.
Пример см. в статье PDO::beginTransaction .
В оставшейся части этой статьи объясняется и демонстрируется, как использовать драйвер SQLSRV для выполнения транзакций.
Замечания
Шаги по выполнению транзакции можно обобщить следующим образом.
Начните транзакцию с помощью sqlsrv_begin_transaction.
Проверьте состояние выполнения каждого запроса, входящего в состав транзакции.
При необходимости зафиксируйте транзакцию с помощью sqlsrv_commit. В противном случае выполните откат транзакции с помощью sqlsrv_rollback. После вызова sqlsrv_commit или sqlsrv_rollback драйвер возвращается в режим автофиксации.
По умолчанию драйверы Майкрософт для PHP для SQL Server используются в режиме автоматической фиксации. Это означает, что все запросы автоматически фиксируются после успешного выполнения, если только они не были обозначены как часть явной транзакции с помощью sqlsrv_begin_transaction.
Если явная транзакция не фиксируется с помощью sqlsrv_commit, при закрытии подключения или прекращении работы сценария выполняется ее откат.
Не используйте внедренный Transact-SQL для выполнения транзакций. Например, не выполняйте инструкцию с BEGIN TRANSACTION в качестве запроса Transact-SQL для начала транзакции. При использовании внедренного Transact-SQL для выполнения транзакций невозможно гарантировать правильную работу транзакций.
Для выполнения транзакций следует использовать перечисленные выше функции sqlsrv .
Пример
Description
Следующий пример выполняет несколько запросов как часть транзакции. Если все запросы выполняются успешно, транзакция фиксируется. В случае сбоя одного из запросов транзакция откатывается.
Пример пытается удалить заказы на продажу из таблицы Sales.SalesOrderDetail и скорректировать уровни запасов в таблице Product.ProductInventory для каждого продукта в заказе на продажу. Поскольку для точного отражения состояния заказов и доступности продуктов требуется успешное выполнение всех запросов в базе данных, эти запросы включены в состав транзакции.
Первый запрос в примере извлекает коды и количество продуктов для идентификатора указанного заказа на продажу. Этот запрос не является частью транзакции. Однако в случае сбоя этого запроса скрипт завершается, так как для выполнения запросов, которые являются частью последующей транзакции, требуются коды и количество продуктов.
Следующие запросы (удаление заказа на продажу и обновление складских запасов продуктов) являются частью транзакции.
В примере предполагается, что SQL Server и базы данных AdventureWorks установлены на локальном компьютере. При выполнении примера из командной строки все выходные данные выводятся в консоль.
Код
<?php
/* Connect to the local server using Windows Authentication and
specify the AdventureWorks database as the database in use. */
$serverName = "(local)";
$connectionInfo = array( "Database"=>"AdventureWorks");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false )
{
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
/* Begin transaction. */
if( sqlsrv_begin_transaction($conn) === false )
{
echo "Could not begin transaction.\n";
die( print_r( sqlsrv_errors(), true));
}
/* Set the Order ID. */
$orderId = 43667;
/* Execute operations that are part of the transaction. Commit on
success, roll back on failure. */
if (perform_trans_ops($conn, $orderId))
{
//If commit fails, roll back the transaction.
if(sqlsrv_commit($conn))
{
echo "Transaction committed.\n";
}
else
{
echo "Commit failed - rolling back.\n";
sqlsrv_rollback($conn);
}
}
else
{
"Error in transaction operation - rolling back.\n";
sqlsrv_rollback($conn);
}
/*Free connection resources*/
sqlsrv_close( $conn);
/*---------------- FUNCTION: perform_trans_ops -----------------*/
function perform_trans_ops($conn, $orderId)
{
/* Define query to update inventory based on sales order info. */
$tsql1 = "UPDATE Production.ProductInventory
SET Quantity = Quantity + s.OrderQty
FROM Production.ProductInventory p
JOIN Sales.SalesOrderDetail s
ON s.ProductID = p.ProductID
WHERE s.SalesOrderID = ?";
/* Define the parameters array. */
$params = array($orderId);
/* Execute the UPDATE statement. Return false on failure. */
if( sqlsrv_query( $conn, $tsql1, $params) === false ) return false;
/* Delete the sales order. Return false on failure */
$tsql2 = "DELETE FROM Sales.SalesOrderDetail
WHERE SalesOrderID = ?";
if(sqlsrv_query( $conn, $tsql2, $params) === false ) return false;
/* Return true because all operations were successful. */
return true;
}
?>
Комментарии
Чтобы уделить основное внимание работе транзакции, в предыдущий пример не включены некоторые рекомендуемые аспекты обработки ошибок. В рабочем приложении рекомендуется проверять каждый вызов функции sqlsrv на наличие ошибок и обрабатывать их соответствующим образом.
См. также
Обновление данных (драйверы Майкрософт для PHP для SQL Server)