如何执行事务
SQL Server Driver for PHP 提供了用于执行事务的三个函数:
本主题说明并演示如何使用这些函数执行事务。
下面概述了执行事务的各个步骤:
- 在执行属于事务一部分的任何查询之前,请首先执行 sqlsrv_begin_transaction。
- 检查属于事务一部分的每个查询的成功与否。
- 如果需要,请使用 sqlsrv_commit 提交事务。否则,使用 sqlsrv_rollback 回滚事务。调用 sqlsrv_commit 或 sqlsrv_rollback 之后,驱动程序将返回到自动提交模式。
备注
默认情况下,SQL Server Driver for PHP 为自动提交模式。也就是说,对所有查询而言,如果未使用 sqlsrv_begin_transaction 将其指定为显式事务的一部分,则这些查询都会在成功完成后自动提交。
备注
如果未使用 sqlsrv_commit 提交显式事务,则该事务会在结束连接或终止脚本时回滚。
备注
不要使用嵌入式 Transact-SQL 来执行事务。例如,不要通过将包含“BEGIN TRANSACTION”的语句作为 Transact-SQL 查询执行来开始一个事务。使用嵌入式 Transact-SQL 执行事务时,无法保证出现预期的事务行为。
应将前面列出的 sqlsrv 函数用于执行事务。示例
下面的示例执行属于事务一部分的多个查询。如果所有查询均成功完成,则提交事务。如果其中任何一个查询失败,则回滚事务。
此示例尝试从 Sales.SalesOrderDetail 表中删除销售一个订单,并在 Product.ProductInventory 表中调整该销售订单中每个产品的库存量。这些查询包含在一个事务中,因为所有查询均必须成功完成,数据库才能准确反映订单状态和产品的可供应情况。
此示例中的第一个查询检索指定的销售订单 ID 的产品 ID 和数量。此查询不是事务的一部分。但是,如果此查询因为完成属于后续事务一部分的查询必需提供产品 ID 和数量而失败,则此脚本将结束。
后续查询(删除销售订单并更新产品库存数量)是事务的一部分。
此示例假定本地计算机上已安装了 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 函数的任何调用是否存在错误并进行相应处理。