T-SQL-foutafhandeling implementeren

Voltooid

Een fout geeft een probleem aan of een opmerkelijk probleem dat zich voordoet tijdens een databasebewerking. Fouten kunnen worden gegenereerd door de SQL Server Database Engine als reactie op een gebeurtenis of fout op systeemniveau; of u kunt toepassingsfouten genereren in uw Transact-SQL code.

Elementen van database-enginefouten

Wat de oorzaak ook is, elke fout bestaat uit de volgende elementen:

  • Foutnummer : uniek nummer waarmee de specifieke fout wordt geïdentificeerd.
  • Foutbericht : tekst die de fout beschrijft.
  • Ernst - numerieke indicatie van de ernstgraad van 1 tot 25.
  • Status : interne statuscode voor de database-enginevoorwaarde.
  • Procedure : de naam van de opgeslagen procedure of trigger waarin de fout is opgetreden.
  • Regelnummer : welke instructie in de batch of procedure heeft de fout gegenereerd.

Systeemfouten

Systeemfouten zijn vooraf gedefinieerd en u kunt ze weergeven in de systeemweergave sys.messages . Wanneer er een systeemfout optreedt, kan SQL Server automatische herstelactie uitvoeren, afhankelijk van de ernst van de fout. Als er bijvoorbeeld een fout met hoge ernst optreedt, kan SQL Server een database offline halen of zelfs de database-engineservice stoppen.

Aangepaste fouten

U kunt fouten genereren in Transact-SQL code om te reageren op toepassingsspecifieke voorwaarden of om informatie aan te passen die naar clienttoepassingen wordt verzonden als reactie op systeemfouten. Deze toepassingsfouten kunnen inline worden gedefinieerd waar ze worden gegenereerd of u kunt ze vooraf definiëren in de tabel sys.messages naast de door het systeem geleverde fouten. De foutnummers die worden gebruikt voor aangepaste fouten, moeten 50001 of hoger zijn.

Als u een aangepast foutbericht wilt toevoegen aan sys.messages, gebruikt u sp_addmessage. De gebruiker voor het bericht moet lid zijn van de vaste serverfuncties sysadmin of serveradmin.

Dit is de sp_addmessage syntaxis:

sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg' 
     [ , [ @lang= ] 'language' ] 
     [ , [ @with_log= ] { 'TRUE' | 'FALSE' } ] 
     [ , [ @replace= ] 'replace' ]

Hier volgt een voorbeeld van een aangepast foutbericht met behulp van deze syntaxis:

sp_addmessage 50001, 10, N’Unexpected value entered’;

Daarnaast kunt u aangepaste foutberichten definiëren, leden van de serverfunctie sysadmin kunnen ook een extra parameter gebruiken, @with_log. Als deze is ingesteld op TRUE, wordt de fout ook vastgelegd in het Windows-toepassingslogboek. Elk bericht dat naar het Windows-toepassingslogboek wordt geschreven, wordt ook naar het SQL Server-foutenlogboek geschreven. Wees verstandig met het gebruik van de @with_log optie, omdat netwerk- en systeembeheerders vaak niet tevreden zijn met toepassingen die 'chatty' zijn in de systeemlogboeken. Als de fout echter moet worden onderbroken door een waarschuwing, moet de fout eerst naar het Windows-toepassingslogboek worden geschreven.

Opmerking

Het genereren van systeemfouten wordt niet ondersteund.

Berichten kunnen worden vervangen zonder ze eerst te verwijderen met behulp van de @replace optie = 'replace'.

De berichten kunnen worden aangepast en er kunnen verschillende worden toegevoegd voor hetzelfde foutnummer voor meerdere talen, op basis van een language_id waarde.

Opmerking

Engelse berichten zijn language_id 1033.

Fouten genereren met RAISERROR

Zowel PRINT als RAISERROR kan worden gebruikt om informatie of waarschuwingsberichten naar toepassingen te retourneren. MET RAISERROR kunnen toepassingen een fout genereren die vervolgens kan worden ondervangen door het aanroepende proces.

RAISERROR

De mogelijkheid om fouten te genereren in T-SQL maakt foutafhandeling in de toepassing eenvoudiger, omdat deze wordt verzonden zoals elke andere systeemfout. RAISERROR wordt gebruikt voor:

  • Hulp bij het oplossen van problemen met T-SQL-code.
  • Controleer de waarden van gegevens.
  • Retourneer berichten die variabele tekst bevatten.

Opmerking

Het gebruik van een PRINT-instructie is vergelijkbaar met het veroorzaken van een fout met ernstniveau 10.

Hier volgt een voorbeeld van een aangepast foutbericht met BEHULP van RAISERROR.

RAISERROR (N'%s %d', -- Message text,
    10, -- Severity,
    1, -- State,
    N'Custom error message number',
    2)

Wanneer het wordt geactiveerd, wordt het volgende teruggegeven:

Custom error message number 2

In het vorige voorbeeld is %d een tijdelijke aanduiding voor een getal en %s een tijdelijke aanduiding voor een tekenreeks is. Bovendien moet u er rekening mee houden dat er geen berichtnummer is vermeld. Wanneer fouten met berichttekenreeksen worden gegenereerd met behulp van deze syntaxis, hebben ze altijd het foutnummer 50000.

Fouten genereren met BEHULP van THROW

De THROW-instructie biedt een eenvoudigere methode voor het afhandelen van fouten in code. Fouten moeten een foutnummer hebben van ten minste 50000.

WERPEN

THROW verschilt op verschillende manieren van RAISERROR:

  • Fouten die worden gegenereerd door THROW, zijn altijd ernst 16.
  • De berichten die door THROW worden geretourneerd, zijn niet gerelateerd aan vermeldingen in sys.sysmessages.
  • Fouten die door THROW worden gegenereerd, veroorzaken alleen een transactie-abortie bij gebruik in combinatie met SET XACT_ABORT ON, en de sessie wordt beëindigd.
THROW 50001, 'An Error Occured',0

Foutcodes vastleggen met behulp van @@Error

De meeste traditionele foutcodes in SQL Server-toepassingen zijn gemaakt met behulp van @@ERROR. Gestructureerde uitzonderingsafhandeling is geïntroduceerd in SQL Server 2005 en biedt een sterk alternatief voor het gebruik van @@ERROR. In de volgende les wordt het besproken. Een grote hoeveelheid bestaande SQL Server-foutcodes is gebaseerd op @@ERROR, dus het is belangrijk om te begrijpen hoe u ermee kunt werken.

@@ERROR

@@ERROR is een systeemvariabele die het foutnummer bevat van de laatste fout die is opgetreden. Een belangrijke uitdaging met @@ERROR is dat de waarde die deze bevat snel opnieuw wordt ingesteld wanneer elke extra instructie wordt uitgevoerd.

Denk bijvoorbeeld aan de volgende code:

RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO

U kunt verwachten dat wanneer de code wordt uitgevoerd, het foutnummer in een afgedrukte tekenreeks wordt geretourneerd. Wanneer de code echter wordt uitgevoerd, wordt het volgende geretourneerd:

Msg 50000, Level 16, State 1, Line 1
Message
Error=0

De fout is gegenereerd, maar het afgedrukte bericht is 'Error=0'. In de eerste regel van de uitvoer ziet u dat de fout, zoals verwacht, eigenlijk 50000 was, met een bericht dat is doorgegeven aan RAISERROR. Dit komt doordat de IF-instructie die volgt op de RAISERROR-instructie succesvol is uitgevoerd en de @@ERROR-waarde opnieuw is ingesteld. Daarom is het belangrijk om bij het werken met @@ERROR het foutnummer vast te leggen in een variabele zodra deze wordt gegenereerd en vervolgens door te gaan met de verwerking met de variabele.

Bekijk de volgende code die dit laat zien:

DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));

Wanneer deze code wordt uitgevoerd, wordt de volgende uitvoer geretourneerd:

Msg 50000, Level 16, State 1, Line 2
Message
Error=50000

Het foutnummer wordt nu correct gerapporteerd.

Foutafhandeling centraliseren

Een ander belangrijk probleem met het gebruik van @@ERROR voor foutafhandeling is dat het moeilijk is om te centraliseren binnen uw T-SQL-code. Foutafhandeling is meestal verspreid door de code. Het zou mogelijk zijn om foutafhandeling te centraliseren met behulp van @@ERROR in zekere mate met behulp van labels en GOTO-instructies. Dit zou echter door de meeste ontwikkelaars tegenwoordig worden afgekeurd als een slechte codeerpraktijk.

Foutwaarschuwingen maken

Voor bepaalde foutencategorieën kunnen beheerders SQL Server-waarschuwingen maken, omdat ze op de hoogte willen worden gesteld zodra deze zich voordoen. Dit kan zelfs van toepassing zijn op door de gebruiker gedefinieerde foutberichten. U kunt bijvoorbeeld een waarschuwing genereren wanneer een transactielogboek wordt ingevuld. Waarschuwingen worden vaak gebruikt om fouten met hoge ernst (zoals ernst 19 of hoger) onder de aandacht van beheerders te brengen.

Waarschuwingen genereren

Waarschuwingen kunnen worden gemaakt voor specifieke foutberichten. De waarschuwingsservice fungeert door zichzelf te registreren als een terugbelservice bij de gebeurtenislogboekdienst. Dit betekent dat waarschuwingen alleen werken op vastgelegde fouten.

Er zijn twee manieren om een foutmelding te genereren: u kunt de optie WITH LOG gebruiken wanneer u de fout opgeeft of het bericht kan worden gewijzigd om het te registreren door sp_altermessage uit te voeren. De optie WITH LOG heeft alleen invloed op de huidige statement. Als u sp_altermessage gebruikt, wordt het foutgedrag voor toekomstig gebruik gewijzigd. Het wijzigen van systeemfouten via sp_altermessage is alleen mogelijk vanaf SQL Server 2005 SP3 of SQL Server 2008 SP1.