Ето пет опции за справяне с грешка Msg 8134 „Открита е грешка при разделяне на нула“ в SQL Server.
Грешката
Първо, ето пример за код, който произвежда грешката, за която говорим:
SELECT 1 / 0;
Резултат:
Msg 8134, Level 16, State 1, Line 1 Divide by zero error encountered.
Получаваме грешката, защото се опитваме да разделим число на нула. Математически това няма никакъв смисъл. Не можете да разделите число на нула и да очаквате смислен резултат.
За да се справим с тази грешка, трябва да решим какво трябва да бъде върнато, когато се опитаме да разделим на нула. Например, може да искаме да бъде върната нулева стойност. Или може да искаме нула да бъде върната. Или някаква друга стойност.
По-долу са някои опции за справяне с тази грешка.
Опция 1:NULLIF()
Израз
Бърз и лесен начин за справяне с тази грешка е да използвате NULLIF()
израз:
SELECT 1 / NULLIF( 0, 0 );
Резултат:
NULL
NULLIF()
връща NULL
ако двата посочени израза са с една и съща стойност. Връща първия израз, ако двата израза са различни. Следователно, ако използваме нула като втори израз, ще получим нулева стойност, когато първият израз е нула. Разделяне на число на NULL
води до NULL
.
Всъщност SQL Server вече връща NULL
при грешка при деление на нула, но в повечето случаи не виждаме това, поради нашия ARITHABORT
и ANSI_WARNINGS
настройки (повече за това по-късно).
Опция 2:Добавете ISNULL()
Функция
В някои случаи може да предпочетете да върнете стойност, различна от NULL
.
В такива случаи можете да предадете предишния пример на ISNULL()
функция:
SELECT ISNULL(1 / NULLIF( 0, 0 ), 0);
Резултат:
0
Тук уточних, че нула трябва да се връща винаги, когато резултатът е NULL
.
Бъдете внимателни все пак. В някои случаи връщането на нула може да е неподходящо. Например, ако имате работа с инвентарни запаси, посочването на нула може да означава, че има нулеви продукти, което може да не е така.
Вариант 3:Използвайте CASE
Изявление
Друг начин да го направите е да използвате CASE
изявление:
DECLARE @n1 INT = 20;
DECLARE @n2 INT = 0;
SELECT CASE
WHEN @n2 = 0
THEN NULL
ELSE @n1 / @n2
END
Резултат:
NULL
Опция 4:SET ARITHABORT
Изявление
SET ARITHABORT
оператор завършва заявка, когато възникне грешка при препълване или деление на нула по време на изпълнение на заявката. Можем да го използваме във връзка с SET ANSI WARNINGS
за да върнете NULL
всеки път, когато може да възникне грешка при деление на нула:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SELECT 20 / 0;
Резултат:
NULL
Microsoft препоръчва винаги да задавате ARITHABORT
до ON
във вашите сесии за влизане и това да го настроите на OFF
може да повлияе негативно на оптимизирането на заявките, което води до проблеми с производителността.
Някои клиенти (като SQL Server Management Studio) задават ARITHABORT
до ON
по подразбиране. Ето защо вероятно не виждате NULL
стойност, която се връща, когато разделите на нула. Можете да използвате SET ARITHIGNORE
за да промените това поведение, ако предпочитате.
Опция 5:SET ARITHIGNORE
Изявление
SET ARITHIGNORE
операторът контролира дали съобщенията за грешка се връщат от грешки при препълване или деление на нула по време на заявка:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SET ARITHIGNORE ON;
SELECT 1 / 0 AS Result_1;
SET ARITHIGNORE OFF;
SELECT 1 / 0 AS Result_2;
Резултат:
Commands completed successfully. Commands completed successfully. Commands completed successfully. +------------+ | Result_1 | |------------| | NULL | +------------+ (1 row affected) Commands completed successfully. +------------+ | Result_2 | |------------| | NULL | +------------+ Division by zero occurred.
Тук задавам ARITHABORT
и ANSI_WARNINGS
до OFF
така че изявлението да не е прекратено поради грешката и NULL
се връща всеки път, когато има грешка при деление на нула.
Обърнете внимание, че SET ARITHIGNORE
настройката контролира само дали се връща съобщение за грешка. SQL Server връща NULL
при изчисление, включващо грешка при препълване или деление на нула, независимо от тази настройка.
В горния пример можем да видим, че когато ARITHIGNORE
е ON
, грешката при деление на нула не се връща. Когато е OFF
, се връща съобщението за грешка при деленето на нула.