Porównanie transakcji i partii

Ukończone

Warto porównać zachowanie partii języka T-SQL ujętego w blok TRY/CATCH na zachowanie transakcji.

Rozważmy następujący kod, który wstawia dwa zamówienia klientów, wymagając wiersza w tabeli SalesLT.SalesOrderHeader i co najmniej jednego wiersza w tabeli SalesLT.SalesOrderDetail . Wszystkie instrukcje INSERT są ujęte w bloku TRY.

  • Jeśli pierwsze wstawianie zakończy się niepowodzeniem, wykonanie przejdzie do bloku CATCH i nie zostanie wykonany żaden kolejny kod.
  • Jeśli drugie wstawianie zakończy się niepowodzeniem, wykonanie przejdzie do bloku CATCH i nie zostanie wykonany żaden kolejny kod. Jednak pierwsze wstawienie zakończyło się pomyślnie i nie zostało wycofane, pozostawiając bazę danych w niespójnym stanie. Wiersz został wstawiony dla zamówienia, ale nie ma wiersza dla szczegółów zamówienia.
BEGIN TRY
	INSERT INTO dbo.Orders(custid, empid, orderdate) 
		VALUES (68, 9, '2021-07-12');
	INSERT INTO dbo.Orders(custid, empid, orderdate) 
		VALUES (88, 3, '2021-07-15');
	INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty) 
		VALUES (1, 2, 15.20, 20);
	INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty) 
		VALUES (999, 77, 26.20, 15);
END TRY
BEGIN CATCH
	SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
END CATCH;

Porównaj to z implementacją kodu w ramach transakcji. Blok TRY/CATCH jest nadal używany do obsługi błędów, jednak instrukcje INSERT dla tabel Orders i OrderDetails są ujęte w słowa kluczowe BEGIN TRANSACTION/COMMIT TRANSACTION. Gwarantuje to, że wszystkie instrukcje są traktowane jako pojedyncza transakcja, która kończy się powodzeniem lub niepowodzeniem. Jeden wiersz jest zapisywany zarówno w tabeli Orders, jak i OrderDetails, albo nie wstawiono żadnego wiersza. W ten sposób baza danych nigdy nie może być w stanie niespójnym.

BEGIN TRY
 BEGIN TRANSACTION;
	INSERT INTO dbo.Orders(custid, empid, orderdate) 
		VALUES (68,9,'2006-07-15');
	INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty) 
		VALUES (99, 2,15.20,20);
	COMMIT TRANSACTION;
END TRY
BEGIN CATCH
 SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
 ROLLBACK TRANSACTION;
END CATCH;