Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Вложени съхранени процедури, съдържащи модел TRY CATCH ROLLBACK?

Това е нашият шаблон (регистрирането на грешки е премахнато)

Това е предназначено да обработва

Обяснения:

  • всички TXN започват и извършват/връщат назад трябва да бъдат сдвоени, така че @@TRANCOUNT е еднакъв при влизане и излизане

  • несъответствия на @@TRANCOUNT причинява грешка 266, защото

    • BEGIN TRAN увеличава @@TRANCOUNT

    • COMMIT намалява @@TRANCOUNT

    • ROLLBACK връща @@TRANCOUNT до нула

  • Не можете да намалявате @@TRANCOUNT за текущия обхват
    Това е, което смятате, че е „вътрешната транзакция“

  • SET XACT_ABORT ON потиска грешка 266, причинена от несъответстващ @@TRANCOUNT
    И също така се справя с проблеми като този "Време за изчакване на транзакция на SQL Server" на dba.se

  • Това позволява TXN от страна на клиента (като LINQ). Една съхранена процедура може да бъде част от разпределена или XA транзакция или просто такава, инициирана в клиентски код (да речем .net TransactionScope)

Употреба:

  • Всеки съхранен процес трябва да отговаря на един и същ шаблон

Резюме

  • Така че не създавайте повече TXN, отколкото са ви необходими

Кодът

CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION;
    THROW;
    --before SQL Server 2012 use 
    --RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

Бележки:

  • Проверката за връщане всъщност е излишна поради SET XACT_ABORT ON . Въпреки това ме кара да се чувствам по-добре, изглежда странно без него и позволява ситуации, в които не го искате

  • Ремус Русану има подобна обвивка който използва точки за запазване. Предпочитам извикване на атомна база данни и не използвам частични актуализации като тяхната статия



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вземете ConnectionString от app.config в c#

  2. Как да гарантирам, че Linq to Sql няма да замени или наруши стойностите по подразбиране на DB, които не могат да бъдат нулеви?

  3. ISJSON() Примери в SQL Server (T-SQL)

  4. Разлика между sys.sql_modules, sys.system_sql_modules и sys.all_sql_modules в SQL Server

  5. SQL IN заявката дава странен резултат