sql >> Database >  >> RDS >> Sqlserver

Geneste opgeslagen procedures die het patroon TRY CATCH ROLLBACK bevatten?

Dit is onze sjabloon (foutregistratie verwijderd)

Dit is ontworpen om

Uitleg:

  • alle TXN-begin- en commit/rollbacks moeten worden gekoppeld zodat @@TRANCOUNT is hetzelfde bij in- en uitstappen

  • mismatches van @@TRANCOUNT fout 266 veroorzaken omdat

    • BEGIN TRAN verhoogt @@TRANCOUNT

    • COMMIT verlaagt @@TRANCOUNT

    • ROLLBACK retourneert @@TRANCOUNT naar nul

  • U kunt @@TRANCOUNT niet verlagen voor de huidige scope
    Dit is wat je zou denken dat de "innerlijke transactie" is

  • SET XACT_ABORT ON onderdrukt fout 266 veroorzaakt door niet-overeenkomende @@TRANCOUNT
    En behandelt ook dit soort problemen "SQL Server Transaction Timeout" op dba.se

  • Dit maakt TXN's aan de clientzijde mogelijk (zoals LINQ). Een enkele opgeslagen procedure kan deel uitmaken van een gedistribueerde of XA-transactie, of gewoon een procedure die is gestart in klantcode (bijvoorbeeld .net TransactionScope)

Gebruik:

  • Elk opgeslagen proces moet voldoen aan dezelfde sjabloon

Samenvatting

  • Maak dus niet meer TXN's aan dan u nodig heeft

De code

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

Opmerkingen:

  • De terugdraaicontrole is eigenlijk overbodig vanwege SET XACT_ABORT ON . Ik voel me er echter beter door, het ziet er vreemd uit zonder, en zorgt voor situaties waarin je het niet wilt hebben

  • Remus Rusanu heeft een vergelijkbare shell die spaarpunten gebruikt. Ik geef de voorkeur aan een atomaire DB-aanroep en gebruik geen gedeeltelijke updates zoals hun artikel



  1. Hoe kan ik een enkele rij vergrendelen in Oracle SQL?

  2. Hoe vraag je een int-kolom op voor een waarde?

  3. Wat is het doel van $CONDITIONS onder --query?

  4. PHP - problemen met het associëren van resultaten en het ophalen ervan in MYSQL