Порівняння транзакцій і пакетів
Радимо порівняти поведінку пакетів T-SQL, взятих у блок TRY/CATCH, з поведінкою транзакцій.
Розглянемо наведений нижче код, який вставляє два замовлення клієнтів, що вимагає рядка в таблиці SalesLT.SalesOrderHeader , і один або кілька рядків у таблиці SalesLT.SalesOrderDetail . Усі оператори INSERT взято в блок TRY.
- Якщо перша вставка завершується невдало, виконання переходить до блоку CATCH, і додатковий код не виконується.
- Якщо не вдається виконати другу вставку, виконання переходить до блоку CATCH і не виконується додатковий код. Однак перша вставка пройшла успішно, і вона не відкотилася, залишивши базу даних у неузгодженому стані. Для замовлення вставлено рядок, але немає рядка для відомостей про замовлення.
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;
Порівняйте це з реалізацією коду в транзакції. Блок TRY/CATCH усе ще використовується для обробки помилок, однак інструкції INSERT для таблиць Orders і OrderDetails взято в ключові слова BEGIN TRANSACTION/COMMIT TRANSACTION. Це гарантує, що всі оператори розглядаються як одна транзакція, яка або досягає успіху, або не вдається. Один рядок записується як до таблиці "Замовлення", так і в orderDetails, або жоден рядок не вставляється. Таким чином, база даних ніколи не може перебувати в неузгодженому стані.
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;