Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách khắc phục “Yêu cầu GIAO DỊCH COMMIT không có GIAO DỊCH BẮT ĐẦU tương ứng” trong SQL Server

Nếu bạn nhận được lỗi Msg 3902, Cấp độ 16, có nội dung “Yêu cầu GIAO DỊCH CAM KẾT không có GIAO DỊCH BẮT ĐẦU tương ứng”, có thể là do bạn gặp phải COMMIT tuyên bố.

Bạn có thể nhận được điều này do triển khai xử lý lỗi và quên rằng bạn đã cam kết hoặc khôi phục giao dịch ở nơi khác trong mã của bạn.

Ví dụ về Lỗi

Dưới đây là một ví dụ đơn giản để giải thích lỗi:

SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;

Kết quả:

(7 rows affected)
Msg 3902, Level 16, State 1, Line 2
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

Điều này sẽ xảy ra nếu SET IMPLICIT_TRANSACTIONS của bạn OFF . Xem bên dưới để biết điều gì sẽ xảy ra khi SET IMPLICIT_TRANSACTIONS ON .

Ví dụ về Lỗi do Xử lý Lỗi

Bạn có thể nhận được điều này do triển khai xử lý lỗi và quên rằng bạn đã cam kết hoặc khôi phục giao dịch ở nơi khác trong mã của bạn.

Ví dụ:

BEGIN TRANSACTION
    BEGIN TRY 

        INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
        VALUES ( 5006, SYSDATETIME(), 1006 );
        
        INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
        VALUES ( 5006, 1, 1, 20, 25.99 );
        
        INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
        VALUES ( 5006, 2, 7, 120, 9.99 );

        COMMIT TRANSACTION;

    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
    END CATCH
COMMIT TRANSACTION;

Kết quả:

(1 row affected)
(1 row affected)
(1 row affected)
Msg 3902, Level 16, State 1, Line 20
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

Trong trường hợp này, tôi đã có COMMIT TRANSACTION trong TRY khối. Vì vậy, đến thời điểm COMMIT TRANSACTION thứ hai đã gặp phải, giao dịch đã được cam kết.

Chúng tôi sẽ thấy như vậy ngay cả khi giao dịch gặp lỗi và được khôi phục. Việc khôi phục sẽ kết thúc giao dịch và do đó, không có COMMIT nào nữa câu lệnh là bắt buộc.

Vì vậy, để khắc phục sự cố này, chúng tôi chỉ cần xóa COMMIT TRANSACTION cuối cùng và mã giao dịch sẽ giống như sau:

BEGIN TRANSACTION
    BEGIN TRY 

        INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
        VALUES ( 5006, SYSDATETIME(), 1006 );
        
        INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
        VALUES ( 5006, 1, 1, 20, 25.99 );
        
        INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
        VALUES ( 5006, 2, 7, 120, 9.99 );

        COMMIT TRANSACTION;
        
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
    END CATCH

Giao dịch ngầm định

Nếu bạn đã bật các giao dịch ngầm định, bạn có thể nhận được các kết quả khác với ví dụ đầu tiên.

Nếu chúng tôi đặt IMPLICIT_TRANSACTIONS thành ON , đây là những gì chúng tôi nhận được:

SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;

Kết quả:

+---------------------------------+----------------+
| ProductName                     | ProductPrice   |
|---------------------------------+----------------|
| Left handed screwdriver         | 25.99          |
| Long Weight (blue)              | 14.75          |
| Long Weight (green)             | 11.99          |
| Sledge Hammer                   | 33.49          |
| Chainsaw                        | 245.00         |
| Straw Dog Box                   | 55.99          |
| Bottomless Coffee Mugs (4 Pack) | 9.99           |
+---------------------------------+----------------+
(7 rows affected)

Không có lỗi nào xảy ra.

Điều này là do, các câu lệnh T-SQL nhất định sẽ tự động bắt đầu một giao dịch khi chúng chạy. Như thể chúng được đặt trước bởi một BEGIN TRANSACTION vô hình tuyên bố.

Khi IMPLICIT_TRANSACTIONS OFF , các câu lệnh này được cam kết tự động. Như thể họ đã thành công nhờ một COMMIT TRANSACTION vô hình tuyên bố. Trong trường hợp này, giao dịch ở chế độ tự động gửi.

Khi IMPLICIT_TRANSACTIONS ON , không có COMMIT TRANSACTION ẩn tuyên bố. Các câu lệnh này vẫn được bắt đầu bởi BEGIN TRANSACTION ẩn , nhưng chúng cần được kết thúc một cách rõ ràng.

Một giao dịch ngầm vẫn được tiến hành cho đến khi nó được cam kết rõ ràng hoặc được khôi phục một cách rõ ràng.

Do đó, trong ví dụ này, COMMIT TRANSACTION đi lạc của chúng tôi thực sự cần thiết để kết thúc giao dịch ngầm.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tạo CHẾ ĐỘ XEM được tham số hóa trong SQL Server 2008

  2. Không thể cắt ngắn bảng vì nó đang được tham chiếu bởi ràng buộc NGOẠI KHÓA?

  3. Các hàm TRIM, LTRIM và RTRIM của SQL Server

  4. Sử dụng OBJECT_NAME () để lấy tên đối tượng từ object_id của nó trong SQL Server

  5. Cách tìm một mục danh sách tại một vị trí được chỉ định trong SQL Server