Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Внедряване на обработка на грешки и транзакции в SQL Server

Въведение

Колкото и усилено да се опитваме да проектираме и разработваме приложения, грешки винаги ще се случват. Има две основни категории – синтаксичните или логическите грешки могат да бъдат или програмни грешки, или последствия от неправилен дизайн на базата данни. В противен случай може да получите грешка поради неправилно въведено от потребителя.

T-SQL (език за програмиране на SQL Server) позволява обработка и на двата типа грешки. Можете да отстраните грешки в приложението и да решите какво трябва да направите, за да избегнете грешки в бъдеще.

Повечето приложения изискват да регистрирате грешки, да прилагате лесно отчитане на грешки и, когато е възможно, да обработвате грешки и да продължите изпълнението на приложението.

Потребителите обработват грешки на ниво изявление. Това означава, че когато стартирате партида от SQL команди и проблемът се случи в последния израз, всичко, което предхожда този проблем, ще бъде ангажирано в базата данни като имплицитни транзакции. Това може да не е това, което желаете.

Релационните бази данни са оптимизирани за изпълнение на пакетни оператори. По този начин трябва да изпълните партида от оператори като една единица и да провалите всички оператори, ако един израз се провали. Можете да постигнете това с помощта на транзакции. Тази статия ще се фокусира както върху обработката на грешки, така и върху транзакциите, тъй като тези теми са силно свързани.

Обработка на SQL грешки

За да симулираме изключения, трябва да ги произведем по повторяем начин. Нека започнем с най-простия пример – деление на нула:

SELECT 1/0

Резултатът описва изхвърлената грешка – Открита е грешка при разделяне на нула . Но тази грешка не беше обработена, регистрирана или персонализирана за създаване на удобно за потребителя съобщение.

Обработката на изключения започва с поставяне на изрази, които искате да изпълните, в блок BEGIN TRY…END TRY.

SQL Server обработва (улавя) грешки в блока BEGIN CATCH…END CATCH, където можете да въведете персонализирана логика за регистриране или обработка на грешки.

Инструкцията BEGIN CATCH трябва да следва непосредствено след оператора END TRY. След това изпълнението се предава от блока TRY към блока CATCH при първата поява на грешка.

Тук можете да решите как да се справите с грешките, дали искате да регистрирате данните за повдигнати изключения или да създадете удобно за потребителя съобщение.

SQL Server има вградени функции, които могат да ви помогнат да извлечете подробности за грешка:

  • ERROR_NUMBER():Връща броя на SQL грешките.
  • ERROR_SEVERITY():Връща нивото на сериозност, което показва вида на срещания проблем и неговото ниво. Нива от 11 до 16 могат да се управляват от потребителя.
  • ERROR_STATE():Връща номера на състоянието на грешката и дава повече подробности за изхвърленото изключение. Използвате номера на грешката, за да търсите в базата знания на Microsoft за конкретни подробности за грешката.
  • ERROR_PROCEDURE():Връща името на процедурата или тригера, в който е възникнала грешката, или NULL, ако грешката не е възникнала в процедурата или тригера.
  • ERROR_LINE():Връща номера на реда, на който е възникнала грешката. Това може да бъде номерът на реда на процедурите или тригерите или номерът на реда в партидата.
  • ERROR_MESSAGE():Връща текста на съобщението за грешка.

Следващият пример показва как да се справят с грешките. Първият пример съдържа Деление на нула грешка, докато второто твърдение е правилно.

BEGIN TRY
   PRINT 1/0  
   SELECT 'Correct text'
END TRY
BEGIN CATCH
   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH

Ако вторият израз се изпълни без обработка на грешки (SELECT „Правилен текст“), той ще успее.

Тъй като ние внедряваме персонализираната обработка на грешки в блока TRY-CATCH, изпълнението на програмата се предава на блока CATCH след грешката в първия израз, а вторият оператор никога не е бил изпълнен.

По този начин можете да промените текста, даден на потребителя, и да контролирате какво ще се случи, ако грешката се случи по-добре. Например регистрираме грешките в регистрационна таблица за по-нататъшен анализ.

Използване на транзакции

Бизнес логиката може да определи, че вмъкването на първия израз е неуспешно, когато вторият оператор е неуспешен, или че може да се наложи да повторите промените на първия израз при неуспех на втория израз. Използването на транзакции ви позволява да изпълнявате партида от оператори като една единица, която или се проваля, или е успешна.

Следващият пример демонстрира използването на транзакции.

Първо, създаваме таблица, за да тестваме съхранените данни. След това използваме две транзакции в блока TRY-CATCH, за да симулираме нещата, които се случват, ако част от транзакцията се провали.

Ще използваме оператора CATCH с оператора XACT_STATE(). Функцията XACT_STATE() се използва за проверка дали транзакцията все още съществува. В случай, че транзакцията се отмени автоматично, ТРАНЗАКЦИЯТА ЗА ВРЪЩАНЕ ще доведе до ново изключение.

Насладете се на следния код:

-- CREATE TABLE TEST_TRAN(VALS INT)

BEGIN TRY
   BEGIN TRANSACTION
       INSERT INTO TEST_TRAN(VALS) VALUES(1);
   COMMIT TRANSACTION  

   BEGIN TRANSACTION
       INSERT INTO TEST_TRAN(VALS) VALUES(2);
       INSERT INTO TEST_TRAN(VALS) VALUES('A'); 
       INSERT INTO TEST_TRAN(VALS) VALUES(3);
   COMMIT TRANSACTION
END TRY
BEGIN CATCH  
   IF XACT_STATE() > 0 ROLLBACK TRANSACTION

   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE

END CATCH

SELECT * FROM TEST_TRAN

-- DROP TABLE TEST_TRAN

Изображението показва стойностите в таблицата TEST_TRAN и съобщенията за грешка:

Както виждате, само първата стойност е била ангажирана. При втората транзакция имахме грешка при преобразуване на типа във втория ред. Така цялата партида се върна назад.

По този начин можете да контролирате какви данни влизат в базата данни и как се обработват партидите.

Генериране на персонализирано съобщение за грешка в SQL

Понякога искаме да създадем персонализирани съобщения за грешки. Обикновено те са предназначени за сценарии, когато знаем, че може да възникне проблем. Можем да създадем свои собствени персонализирани съобщения, казващи, че нещо не е наред, без да показваме технически подробности. За това използваме ключовата дума THROW.

BEGIN TRY
   IF ( SELECT COUNT(sys.all_objects) > 1 )
	THROW ‘More than one object is ALL_OBJECTS system table’
END TRY
BEGIN CATCH
   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH

Или бихме искали да имаме каталог с персонализирани съобщения за грешки за категоризиране и последователност на наблюдението и отчитането на грешки. SQL Server ни позволява да дефинираме предварително кода на съобщението за грешка, сериозността и състоянието.

Съхранена процедура, наречена „sys.sp_addmessage“, се използва за добавяне на персонализирани съобщения за грешки. Можем да го използваме, за да извикаме съобщението за грешка на няколко места.

Можем да извикаме RAISERROR и да изпратим номера на съобщението като параметър, вместо да кодираме едни и същи подробности за грешката на множество места в кода.

Като изпълним избрания код отдолу, ние добавяме персонализираната грешка в SQL Server, повдигаме я и след това използваме sys.sp_dropmessage за да премахнете определеното потребителско съобщение за грешка:

exec sys.sp_addmessage @msgnum=55000, @severity = 11, 
                                          @msgtext = 'My custom error message'
GO

RAISERROR(55000,11,1)
GO

exec sys.sp_dropmessage @msgnum=55000
GO

Също така можем да видим всички съобщения в SQL Server, като изпълним формуляра за заявка по-долу. Нашето персонализирано съобщение за грешка се вижда като първи елемент в набора от резултати:

SELECT * FROM master.dbo.sysmessages

Създайте система за регистриране на грешки

Винаги е полезно да регистрирате грешки за по-късно отстраняване на грешки и обработка. Можете също да поставите тригери в тези регистрирани таблици и дори да настроите имейл акаунт и да станете малко креативни в начина, по който уведомявате хората, когато възникне грешка.

За да регистрираме грешки, създаваме таблица, наречена DBError_Log , който може да се използва за съхраняване на подробни данни от дневника:

CREATE TABLE DBError_Log
(
    DBError_Log_ID    INT IDENTITY(1, 1) PRIMARY KEY,
    UserName              VARCHAR(100),
    ErrorNumber    INT,
    ErrorState     INT,
    ErrorSeverity  INT,
    ErrorLine      INT,
    ErrorProcedure VARCHAR(MAX),
    ErrorMessage   VARCHAR(MAX),
    ErrorDateTime  DATETIME
);

За да симулираме механизма за регистриране, създаваме GenError съхранена процедура, която генерира Деление на нула грешка и записва грешката в DBError_Log таблица:

CREATE PROCEDURE dbo.GenError
AS
  BEGIN TRY
    SELECT 1/0
  END TRY
  BEGIN CATCH
    INSERT INTO dbo.DBError_Log
    VALUES
    (SUSER_SNAME(),
     ERROR_NUMBER(),
     ERROR_STATE(),
     ERROR_SEVERITY(),
     ERROR_LINE(),
     ERROR_PROCEDURE(),
     ERROR_MESSAGE(),
     GETDATE()
	);
  END CATCH
GO

EXEC dbo.GenError
SELECT * FROM  dbo.DBError_Log

DBError_Log таблицата съдържа цялата информация, която ни е необходима, за да отстраним грешката. Освен това предоставя допълнителна информация за процедурата, която е причинила грешката. Въпреки че това може да изглежда като тривиален пример, можете да разширите тази таблица с допълнителни полета или да я използвате, за да я попълните с персонализирани изключения.

Заключение

Ако искаме да поддържаме и да отстраняваме грешки в приложенията, най-малкото искаме да съобщим, че нещо се е объркало и също да го регистрираме под капака. Когато имаме приложение на производствено ниво, използвано от милиони потребители, последователната и отчетлива обработка на грешки е ключът към отстраняването на проблеми по време на изпълнение.

Въпреки че бихме могли да регистрираме оригиналната грешка в регистъра за грешки в базата данни, потребителите трябва да виждат по-приятелско съобщение. По този начин би било добра идея да внедрите персонализирани съобщения за грешка, които се изпращат към извикващи приложения.

Какъвто и дизайн да приложите, трябва да регистрирате и обработвате потребителски и системни изключения. Тази задача не е трудна със SQL Server, но трябва да я планирате от самото начало.

Добавянето на операции за обработка на грешки в бази данни, които вече се изпълняват в производство, може да включва сериозно преработване на код и трудно откриваеми проблеми с производителността.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използвайте Създаване на изявление за създаване на таблица в SQL Server - SQL Server / T-SQL урок, част 34

  2. Как да създадете съхранена процедура в SQL Server

  3. Как да разбера какво заключва масите ми?

  4. Какво представляват ограниченията на базата данни?

  5. 3 области, които ще се възползват от използването на инструмент за наблюдение на производителността на SQL Server