Porównanie transakcji i partii
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;