Implementarea gestionării erorilor T-SQL

Finalizat

O eroare indică o problemă sau o problemă notabilă care apare în timpul unei operațiuni de bază de date. Erorile pot fi generate de motorul de baze de date SQL Server ca răspuns la un eveniment sau la o eroare la nivel de sistem; sau puteți genera erori de aplicație în codul Transact-SQL.

Elemente ale erorilor motorului de baze de date

Indiferent de cauză, fiecare eroare este compusă din următoarele elemente:

  • Număr eroare - număr unic care identifică eroarea specifică.
  • Mesaj de eroare - text care descrie eroarea.
  • Severitate - indicație numerică de gravitate de la 1 la 25.
  • State - cod de stare intern pentru condiția motorului bazei de date.
  • Procedure - numele procedurii stocate sau al triggerului în care a apărut eroarea.
  • Număr de linie - care instrucțiune din lot sau procedură a generat eroarea.

Erori de sistem

Erorile de sistem sunt predefinite și le puteți vizualiza în vizualizarea system sys.messages . Atunci când apare o eroare de sistem, SQL Server poate efectua o acțiune de remediere automată, în funcție de severitatea erorii. De exemplu, atunci când apare o eroare de severitate mare, SQL Server poate lua o bază de date offline sau chiar poate opri serviciul motorului de baze de date.

Erori particularizate

Puteți genera erori în cod Transact-SQL pentru a răspunde la condiții specifice aplicației sau pentru a particulariza informațiile trimise aplicațiilor client ca răspuns la erorile de sistem. Aceste erori de aplicație pot fi definite în linie unde sunt generate sau le puteți defini în tabelul sys.messages împreună cu erorile furnizate de sistem. Numerele de eroare utilizate pentru erorile particularizate trebuie să fie 50001 sau o versiune mai recentă.

Pentru a adăuga un mesaj de eroare particularizat la sys.messages, utilizați sp_addmessage. Utilizatorul pentru mesaj trebuie să fie membru al rolurilor de server fixe sysadmin sau serveradmin.

Aceasta este sintaxa sp_addmessage:

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

Iată un exemplu de mesaj de eroare particularizat utilizând această sintaxă:

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

În plus, puteți defini mesaje de eroare particularizate, membrii rolului de server sysadmin pot utiliza, de asemenea, un parametru suplimentar , @with_log. Atunci când este setată la TRUE, eroarea va fi înregistrată și în jurnalul de aplicații Windows. Orice mesaj scris în jurnalul de aplicații Windows este scris și în jurnalul de erori SQL Server. Fiți judicios cu utilizarea opțiunii @with_log , deoarece administratorii de rețea și de sistem tind să nu-și placă aplicațiile care sunt "chatty" în jurnalele de sistem. Cu toate acestea, dacă eroarea trebuie să fie prinsă de o avertizare, eroarea trebuie să fie scrisă mai întâi în jurnalul de aplicații Windows.

Notă

Creșterea erorilor de sistem nu este acceptată.

Mesajele pot fi înlocuite fără a le șterge mai întâi, utilizând opțiunea @replace = "înlocuire".

Mesajele se pot particulariza și pot fi adăugate altele diferite pentru același număr de eroare pentru mai multe limbi, pe baza unei valori de language_id.

Notă

Mesajele în limba engleză sunt language_id 1033.

Ridicați erorile utilizând RAISERROR

Atât PRINT, cât și RAISERROR pot fi utilizate pentru a returna informații sau a avertiza mesaje la aplicații. RAISERROR permite aplicațiilor să ridice o eroare care ar putea fi apoi prinsă de procesul de apelare.

RIDICAREA TERORII

Capacitatea de a ridica erorile din T-SQL simplifică gestionarea erorilor în aplicație, deoarece este trimisă ca orice altă eroare de sistem. RAISERROR se utilizează pentru:

  • Ajutați la depanarea codului T-SQL.
  • Verificați valorile datelor.
  • Returnează mesajele care conțin text variabil.

Notă

Utilizarea unei instrucțiuni PRINT este similară cu creșterea unei erori de severitate 10.

Iată un exemplu de mesaj de eroare particularizat utilizând RAISERROR.

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

Când se declanșează, ea returnează:

Custom error message number 2

În exemplul anterior, %d este un substituent pentru un număr și %s este un substituent pentru un șir. În plus, ar trebui să rețineți că nu a fost menționat un număr de mesaj. Atunci când sunt ridicate erori cu șirurile de mesaje utilizând această sintaxă, ele au întotdeauna numărul de eroare 50000.

Ridicați erorile utilizând THROW

Instrucțiunea THROW oferă o metodă mai simplă de a ridica erorile în cod. Erorile trebuie să aibă un număr de eroare de cel puțin 50000.

ARUNCA

THROW diferă de RAISERROR în mai multe moduri:

  • Erorile ridicate de THROW sunt întotdeauna severitate 16.
  • Mesajele returnate de THROW nu sunt legate de nicio intrare din sys.sysmessages.
  • Erorile ridicate de THROW provoacă doar abandonarea tranzacției atunci când este utilizată împreună cu SET XACT_ABORT ON și sesiunea este terminată.
THROW 50001, 'An Error Occured',0

Capturarea codurilor de eroare utilizând @@Error

Cel mai tradițional cod de tratare a erorilor din aplicațiile SQL Server a fost creat utilizând @@ERROR. Gestionarea excepțiilor structurate a fost introdusă în SQL Server 2005 și oferă o alternativă puternică la utilizarea @@ERROR. Va fi discutată în următoarea lecție. Un volum mare de cod existent de tratare a erorilor SQL Server se bazează pe @@ERROR, deci este important să înțelegeți cum să lucrați cu acesta.

@@ERROR

@@ERROR este o variabilă de sistem care conține numărul de eroare al ultimei erori care a apărut. O provocare semnificativă cu @@ERROR este că valoarea pe care o deține este resetat rapid, pe măsură ce se execută fiecare instrucțiune suplimentară.

De exemplu, luați în considerare următorul cod:

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

Este posibil să vă așteptați ca, atunci când se execută codul, să returneze numărul de eroare dintr-un șir imprimat. Cu toate acestea, atunci când se execută codul, acesta returnează:

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

Eroarea a fost ridicată, dar mesajul imprimat a fost "Eroare=0". În prima linie a rezultatului, puteți vedea că eroarea, așa cum vă așteptați, a fost de fapt 50000, cu un mesaj transmis la RAISERROR. Aceasta deoarece instrucțiunea IF care urmează declarației RAISERROR a fost executată cu succes și a determinat reinițializare valoarea @@ERROR. Din acest motiv, atunci când lucrați cu @@ERROR, este important să capturați numărul de eroare într-o variabilă imediat ce este ridicat, apoi să continuați procesarea cu variabila.

Priviți următorul cod care demonstrează acest lucru:

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

Atunci când acest cod este executat, returnează următoarea ieșire:

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

Numărul de eroare este raportat corect acum.

Centralizarea gestionării erorilor

O altă problemă semnificativă cu utilizarea @@ERROR pentru gestionarea erorilor este că este dificil să centralizați în codul T-SQL. Gestionarea erorilor tinde să se împrăștie prin cod. Ar fi posibil să centralizați gestionarea erorilor utilizând @@ERROR într-o anumită măsură, utilizând etichete și instrucțiuni GOTO. Cu toate acestea, acest lucru ar fi încruntat de către majoritatea dezvoltatorilor de astăzi ca o practică de codare slabă.

Crearea avertizărilor de eroare

Pentru anumite categorii de erori, administratorii pot crea avertizări SQL Server, deoarece doresc să fie notificați imediat ce apar. Acest lucru se poate aplica chiar și la mesajele de eroare definite de utilizator. De exemplu, poate doriți să ridicați o avertizare de fiecare dată când se completează un jurnal de tranzacții. Alertarea este utilizată de obicei pentru a aduce erorile de severitate înaltă (cum ar fi severitatea 19 sau o versiune mai recentă) în atenția administratorilor.

Creșterea avertizărilor

Avertizările pot fi create pentru anumite mesaje de eroare. Serviciul de avertizare funcționează prin înregistrarea propriu-zisă ca serviciu de apelare inversă cu serviciul de înregistrare în jurnal a evenimentelor. Acest lucru înseamnă că avertizările funcționează doar la erorile înregistrate.

Există două modalități de a face o eroare să ridice o avertizare: puteți utiliza opțiunea WITH LOG atunci când ridicați eroarea sau mesajul poate fi modificat pentru a-l face conectat prin executarea sp_altermessage. Opțiunea WITH LOG afectează doar instrucțiunea curentă. Utilizarea sp_altermessage modifică comportamentul erorii pentru toate utilizările viitoare. Modificarea erorilor de sistem prin sp_altermessage este posibilă numai din SQL Server 2005 SP3 sau SQL Server 2008 SP1 începând cu versiunile anterioare.