Foutafhandeling en logging in SQL zijn bijzonder populair geworden met de ontwikkeling van complexe bedrijfsprocessen, waar het belangrijk werd om de uitvoering bij een fout niet alleen te stoppen, maar ook het feit van een storing vast te leggen en, indien mogelijk, door te gaan met werken. Aanvankelijk had SQL geen ontwikkelde middelen zoals try-catch, en iedere RDBMS bood zijn eigen mechanismen aan.
Geschiedenis van de vraag:
Vroege versies van SQL-standaarden hadden geen ingebouwde operators voor het opvangen van fouten in procedures. Later begonnen fabrikanten structuren te implementeren, zoals TRY...CATCH in Microsoft SQL Server, of HANDLER in MySQL, waardoor de werkstroom flexibeler kan worden gecontroleerd op database-niveau.
Probleem:
Fouten kunnen ontstaan door onjuiste gegevens of door systeemredenen. Als er in de opgeslagen procedure geen foutopsporing en registratie is geïmplementeerd, wordt debugging en onderhoud zeer moeilijk. Bovendien is het noodzakelijk om kritieke fouten en behandelde fouten te kunnen onderscheiden, zodat de uitvoering van de bedrijfsoperatie daar waar nodig, niet wordt onderbroken.
Oplossing:
In moderne systemen moeten structuren voor het verzamelen en loggen van fouten worden geïmplementeerd. Het is noodzakelijk om aparte logtabellen te maken, TRY...CATCH (SQL Server) of DECLARE ... HANDLER (MySQL) te gebruiken, gedetailleerde informatie over uitzonderingen op te slaan om de oorzaken van falen later te analyseren.
Voorbeeldcode (SQL Server):
CREATE PROCEDURE dbo.UpdateCustomer @CustomerID INT, @NewName NVARCHAR(100) AS BEGIN BEGIN TRY UPDATE Customers SET Name = @NewName WHERE CustomerID = @CustomerID; END TRY BEGIN CATCH INSERT INTO ErrorLog (ErrorMessage, ErrorSeverity, ErrorTime) VALUES (ERROR_MESSAGE(), ERROR_SEVERITY(), GETDATE()); THROW; END CATCH END;
Belangrijke kenmerken:
Kunnen alle soorten fouten binnen een TRY...CATCH-blok (of via handler) worden opgevangen?
Nee, niet alle fouten kunnen worden opgevangen, bijvoorbeeld fatale serverfouten kunnen niet worden onderschept. Fouten zoals "Attention," of verbindingsfouten vallen buiten de transactieverwerking.
Wat gebeurt er met ongecommitteerde wijzigingen in de procedure bij een fout, als er geen transactie wordt gebruikt?
Wijzigingen worden gedeeltelijk vastgelegd, een deel van de updates komt in de database, terwijl een ander deel mogelijk verloren gaat. Om inconsistentie te voorkomen, wordt aangeraden altijd transacties te gebruiken.
BEGIN TRY BEGIN TRANSACTION; --...code COMMIT; END TRY BEGIN CATCH ROLLBACK; END CATCH
Kan je INSERT EXEC direct vanuit het CATCH-blok gebruiken om een fout vanuit een andere context te registreren?
Niet altijd: INSERT EXEC is verboden in meerdere contexten (bijvoorbeeld als er al een actieve transactie is), wat fouten van de tweede laag kan veroorzaken. Het is beter om de foutdetails lokaal te verzamelen en ze vervolgens met een enkele INSERT in te voegen.
Een klant implementeerde de logica alleen via RAISERROR zonder logging, waardoor fouten niet werden opgeslagen en geanalyseerd.
Voordelen:
Nadelen:
Gebruik van TRY...CATCH plus de ErrorLog-tabel, registratie van tijd, foutcode, gebruiker, tekst en trace.
Voordelen:
Nadelen: