如何执行事务

SQL Server Driver for PHP 提供了用于执行事务的三个函数:

本主题说明并演示如何使用这些函数执行事务。

下面概述了执行事务的各个步骤:

  1. 在执行属于事务一部分的任何查询之前,请首先执行 sqlsrv_begin_transaction
  2. 检查属于事务一部分的每个查询的成功与否。
  3. 如果需要,请使用 sqlsrv_commit 提交事务。否则,使用 sqlsrv_rollback 回滚事务。调用 sqlsrv_commitsqlsrv_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 函数的任何调用是否存在错误并进行相应处理。

另请参见

概念

关于文档中的代码示例

其他资源

更新数据 (SQL Server Driver for PHP)