dibattito sullo sviluppo T-SQL, che è l'approccio corretto

3

La società in cui lavoro utilizza le stored procedure (e un ORM interno) esclusivamente per l'interazione con tutti i database, seleziona, aggiorna, elimina.

Abbiamo numerosi procs che inseriranno e / o aggiorneranno e / o elimineranno dalle tabelle.

Quando è necessario "transazionalizzare" un intero proc, ovviamente abbiamo bisogno di avere le nostre dichiarazioni commit e rollback .

Ecco dove arriva la domanda.

Quando ci sono più istruzioni in una transazione che devono essere confermate o riavvolte insieme, ovviamente lanciamo un blocco try / catch attorno a tutto.

Supponiamo questo scenario di esempio per uno script:

set nocount on

create table #test
(
    id int primary key identity(1,1),
    col varchar(2) not null,
    y int not null
)

begin tran

begin try
    insert into #test ( col, y ) values ('GA', 4)
    update #test set col = 'DO', y = y / 0
    insert into #test ( col, y ) values ('aa', 7)
    commit
end try
begin catch
    select error_message()
    rollback
end catch

select * from #test t

drop table #test

Ora, questo è il modo in cui scriverei lo script.

Supponiamo che l'istruzione update (la seconda istruzione) causi un'eccezione. Dovrebbe quindi spostare lo stato attivo sul blocco catch e quindi eseguire il comando rollback annullando tutto il lavoro eseguito in insert .

ESSI dicono che, per fare in modo che rollback esegua effettivamente il rollback di TUTTE le istruzioni anziché quella che ha causato l'eccezione, è necessario scrivere lo script in questo modo:

set nocount on
set xact_abort on ------------------------------------------------

create table #test
(
    id int primary key identity(1,1),
    col varchar(2) not null,
    y int not null
)

begin tran

begin try
    insert into #test ( col, y ) values ('GA', 4)
    update #test set col = 'DO', y = y / 0
    insert into #test ( col, y ) values ('aa', 7)
    commit
end try
begin catch
    select error_message()
    if (xact_state() <> 0) -------------------------------------------------
        rollback
end catch

select * from #test t

drop table #test

Ora, quando provo entrambi questi esempi, entrambi ottengono lo stesso risultato desiderato (nessun record nella tabella).

Che senso ha fare la roba xact_abort e xact_state quando il semplice wrapping di più istruzioni in un try / catch realizza la stessa cosa (ripristinando più istruzioni quando c'è un'eccezione)?

    
posta ganders 02.09.2016 - 21:13
fonte

1 risposta

1

Questo sarebbe meglio su dba.stackexchange.com

XACT_STATE () non influisce sul comportamento del rollback. Si tratta di stato.

1 The current request has an active user transaction. The request can perform any actions, including writing data and committing the transaction.
0 There is no active user transaction for the current request.
-1 The current request has an active user transaction, but an error has occurred that has caused the transaction to be classified as an uncommittable transaction. The request cannot commit the transaction or roll back to a savepoint; it can only request a full rollback of the transaction. The request cannot perform any write operations until it rolls back the transaction. The request can only perform read operations until it rolls back the transaction. After the transaction has been rolled back, the request can perform both read and write operations and can begin a new transaction.

SET XACT_ABORT

Specifies whether SQL Server automatically rolls back the current transaction when a Transact-SQL statement raises a run-time error.

Hai un tentativo di CATCH. Un errore / eccezione causerà un problema e il catch richiamerà il ROLLBACK. XACT_ABORT non ha effetto su un ROLLBACK esplicito.

Guarda l'esempio nel link. Il secondo dovrebbe eseguire il rollback anche senza un try catch.

Per prima cosa scommetto che verrà eseguito il rollback anche con set xact_abort disattivato.

    
risposta data 25.10.2016 - 17:25
fonte

Leggi altre domande sui tag