방법: 트랜잭션 수행
Microsoft Drivers for PHP for SQL Server의 SQLSRV 드라이버는 트랜잭션을 수행하기 위해 다음의 세 가지 함수를 제공합니다.
PDO_SQLSRV 드라이버는 트랜잭션을 수행하기 위해 세 가지 메서드를 제공합니다.
예시는 PDO::beginTransaction을 참조하세요.
이 항목의 나머지 부분에서는 SQLSRV 드라이버를 사용하여 트랜잭션을 수행하는 방법을 설명하고 데모를 제공합니다.
설명
트랜잭션을 실행하는 단계는 다음과 같이 요약할 수 있습니다.
sqlsrv_begin_transaction을 사용하여 트랜잭션을 시작합니다.
트랜잭션의 일부인 각 쿼리의 성공 또는 실패를 확인합니다.
해당하는 경우 sqlsrv_commit을 사용하여 트랜잭션을 커밋합니다. 그렇지 않으면 sqlsrv_rollback을 사용하여 트랜잭션을 시작합니다. sqlsrv_commit 또는 sqlsrv_rollback 호출한 후 드라이버는 자동 커밋 모드로 반환됩니다.
기본적으로 MICROSOFT Drivers for PHP for SQL Server는 자동 커밋 모드입니다. 즉, 모든 쿼리는 sqlsrv_begin_transaction을 사용하여 명시적 트랜잭션의 일부로 지정하는 경우를 제외하고 성공 시 자동으로 커밋됩니다.
명시적 트랜잭션이 sqlsrv_commit으로 커밋되지 않으면 연결이 닫히거나 스크립트가 종료될 때 롤백됩니다.
포함된 Transact-SQL을 사용하여 트랜잭션을 수행하지 마세요. 예를 들어, 트랜잭션을 시작하기 위해 Transact-SQL 쿼리로 "BEGIN TRANSACTION"이 있는 문을 실행하지 않습니다. 포함된 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 함수 호출에 오류가 있는지 확인하고 적절하게 처리하는 것이 좋습니다.