如何:執行交易
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 資料表中的產品存貨量。這些查詢包含在交易內,因為所有查詢都必須要成功,資料庫才能正確反映訂單的狀態和產品的可用性。
範例中的第一個查詢會針對指定的銷售訂單識別碼來擷取產品識別碼和數量。此查詢不是交易的一部分。但是,如果此查詢失敗,指令碼就會結束,因為後續交易之一部分的完整查詢需要產品識別碼和數量。
隨後的查詢 (刪除銷售訂單及更新產品存貨數量) 為交易的一部分。
此範例假設 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 函數的任何呼叫,看看是否有錯誤並加以處理。