Par défaut, les transactions ne sont, la plupart du temps, pas automatiquement annulées / annulées lorsqu'une erreur se produit. Ce n'est généralement pas un problème tant que vous gérez correctement les erreurs et appelez- ROLLBACKvous. Cependant, parfois les choses se compliquent, comme dans le cas d'erreurs d'abandon par lots, ou lors de l'utilisation OPENQUERY(ou des serveurs liés en général) et une erreur se produit sur le système distant. Alors que la plupart des erreurs peuvent être piégées en utilisant TRY...CATCH, il y en a deux qui ne peuvent pas être piégées de cette façon (cependant, je ne me souviens pas lesquelles pour le moment - recherche). Dans ces cas, vous devez utiliser SET XACT_ABORT ONpour annuler correctement la transaction.
SET XACT_ABORT ON fait que SQL Server annule immédiatement toute transaction (si une est active) et abandonne le lot si une erreur se produit. Ce paramètre existait avant SQL Server 2005, qui a introduit la TRY...CATCHconstruction. Pour la plupart, TRY...CATCHgère la plupart des situations et rend donc la plupart du temps obsolète XACT_ABORT ON. Cependant, lors de l'utilisation OPENQUERY(et éventuellement d'un autre scénario dont je ne me souviens pas pour le moment), vous devrez toujours l'utiliser SET XACT_ABORT ON;.
Vous devez toujours avoir une gestion des erreurs appropriée, en particulier lorsque vous utilisez des transactions. La TRY...CATCHconstruction, introduite dans SQL Server 2005, fournit un moyen de gérer presque toutes les situations, une amélioration bienvenue par rapport aux tests @@ERRORaprès chaque instruction, ce qui n'a pas beaucoup aidé avec les erreurs d'abandon de lot.
TRY...CATCHintroduit un nouvel «État». Lorsque vous n'utilisez pas la TRY...CATCHconstruction, si vous avez une transaction active et qu'une erreur se produit, plusieurs chemins peuvent être empruntés:
XACT_ABORT OFFet erreur d'abandon de l'instruction: la transaction est toujours active et le traitement se poursuit avec l' instruction suivante , le cas échéant.
XACT_ABORT OFFet la plupart des erreurs d'abandon de lot: la transaction est toujours active et le traitement se poursuit avec le lot suivant , le cas échéant.
XACT_ABORT OFFet certaines erreurs d'abandon de lot: la transaction est annulée et le traitement se poursuit avec le lot suivant , le cas échéant.
XACT_ABORT ONet toute erreur: la transaction est annulée et le traitement se poursuit avec le lot suivant , le cas échéant.
TOUTEFOIS, lors de l'utilisation TRY...CATCH, les erreurs d'abandon de lot n'interrompent pas le lot, mais transfèrent plutôt le contrôle au CATCHbloc. Lorsque XACT_ABORTc'est le cas OFF, la transaction sera toujours active la grande majorité du temps, et vous devrez COMMIT, ou très probablement, le faire ROLLBACK. Mais lorsque vous rencontrez certaines erreurs d'abandon de lot (comme avec OPENQUERY), ou quand XACT_ABORTc'est le cas ON, la transaction sera dans un nouvel état, "non engageable". Dans cet état, vous ne pouvez COMMITni ne pouvez effectuer aucune opération DML. Tout ce que vous pouvez faire est ROLLBACKet SELECTdéclarations. Cependant, dans cet état "incontrôlable", la transaction a été annulée lors de l'erreur qui s'est produite, et l'émission de la ROLLBACKest juste une formalité, mais celle qui doit être effectuée.
Une fonction, XACT_STATE , peut être utilisée pour déterminer si une transaction est active, non engageable ou n'existe pas. Il est recommandé (par certains, au moins) de vérifier cette fonction dans le CATCHbloc pour déterminer si le résultat est -1(c'est-à-dire non engageable) au lieu de tester si @@TRANCOUNT > 0. Mais avec XACT_ABORT ON, cela devrait être le seul état possible, il semble donc que les tests pour @@TRANCOUNT > 0et XACT_STATE() <> 0soient équivalents. D'un autre côté, quand XACT_ABORTest OFFet qu'il y a une Transaction active, alors il est possible d'avoir un état de 1ou -1dans le CATCHbloc, ce qui permet la possibilité d'émettre à la COMMITplace de ROLLBACK(bien que, je ne puisse pas penser à un cas où quelqu'un voudraitCOMMITsi la transaction est validable). Vous trouverez plus d'informations et de recherches sur l'utilisation XACT_STATE()dans un CATCHbloc avec XACT_ABORT ONdans ma réponse à la question DBA.SE suivante: dans quels cas une transaction peut-elle être validée depuis l'intérieur du bloc CATCH lorsque XACT_ABORT est défini sur ON? . Veuillez noter qu'il existe un bogue mineur XACT_STATE()qui le fait renvoyer à tort 1dans certains scénarios: XACT_STATE () renvoie 1 lorsqu'il est utilisé dans SELECT avec certaines variables système mais sans clause FROM
spNewBilling3renvoie une erreur, mais que vous ne souhaitez pas revenir en arrièrespNewBilling2ouspNewBilling1, supprimez simplement[begin|rollback|commit] transaction createSavebillinginvoicedespSavesomename.