Ошибка divide by zero
Как избежать ошибки «divide by zero» в SQL?
У меня есть это сообщение об ошибке:
Msg 8134, Уровень 16, состояние 1, строка 1 деление на ноль обнаруженной ошибки.
Как лучше всего написать код SQL, чтобы я никогда больше не видел этого сообщения об ошибке?
Я мог бы сделать одно из следующих действий:
- Добавьте предложение where, чтобы мой делитель никогда не был равен нулю
- Я мог бы добавить заявление о случае, так что существует специальный режим для нуля.
Является ли лучшим способом использовать предложение NULLIF ?
Есть ли лучший способ, или как это можно сделать?
18 Ответов
Чтобы избежать ошибки «Division by zero», мы запрограммировали его следующим образом:
Но вот гораздо более приятный способ сделать это:
Теперь единственная проблема-запомнить бит NullIf, если я использую ключ»/».
В случае, если вы хотите вернуть ноль, в случае, если произойдет нулевое деление, вы можете использовать:
Для каждого делителя, который равен нулю, вы получите ноль в результирующем наборе.
Это казалось лучшим решением для моей ситуации, когда я пытался решить проблему деления на ноль, что действительно происходит в моих данных.
Предположим, вы хотите вычислить соотношение мужчин и женщин для различных школьных клубов, но обнаруживаете, что следующий запрос не выполняется и выдает ошибку divide-by-zero, когда он пытается вычислить соотношение для клуба «Властелин колец», в котором нет женщин:
Вы можете использовать функцию NULLIF , чтобы избежать деления на ноль. NULLIF сравнивает два выражения и возвращает null, если они равны или первое выражение иначе.
Перепишите запрос следующим образом:
Любое число, разделенное на NULL , дает NULL , и никакой ошибки не возникает.
Вы также можете сделать это в начале запроса:
Поэтому, если у вас есть что-то вроде 100/0 , он вернет NULL. Я сделал это только для простых запросов, поэтому я не знаю, как это повлияет на более длинные/сложные запросы.
РЕДАКТИРОВАТЬ: Я получаю много понижений по этому recently. so я думал, что просто добавлю примечание, что этот ответ был написан до того, как вопрос подвергся самому последнему редактированию, где возвращение null было выделено как option. which кажется очень приемлемым. Некоторые из моих ответов были адресованы таким проблемам, как Эдвардо в комментариях, который, казалось, выступал за возвращение 0. Это тот случай, против которого я выступал.
ANSWER: Я думаю, что здесь есть основная проблема, которая заключается в том, что деление на 0 не является законным. Это признак того, что что-то фундаментально неправильно. Если вы делите на ноль, вы пытаетесь сделать что-то, что не имеет математического смысла, поэтому никакой числовой ответ, который вы можете получить, не будет действительным. (Использование null в этом случае является разумным, поскольку это не то значение, которое будет использоваться в последующих математических расчетах).
Поэтому Эдвардо спрашивает в комментариях: «что, если пользователь ставит 0?», и он отстаивает, что это должно быть нормально, чтобы получить 0 в ответ. Если пользователь кладет ноль в сумму, и вы хотите, чтобы 0 возвращалось, когда они это делают, то вы должны ввести код на уровне бизнес-правил, чтобы поймать это значение и вернуть 0. not есть какой-то особый случай, когда деление на 0 = 0.
Это тонкое различие, но это important. because в следующий раз, когда кто-то вызывает вашу функцию и ожидает, что она сделает все правильно, и она делает что-то фанковое, что не является математически правильным, но просто обрабатывает конкретный крайний случай, у которого есть хороший шанс укусить кого-то позже. На самом деле вы не делите на 0. you’re, а просто возвращаете плохой ответ на плохой вопрос.
Представьте себе, что я что-то кодирую, и я все испорчу. Я должен был бы читать в значении масштабирования измерения излучения, но в странном случае края я не ожидал, я читал в 0. Затем я опускаю свое значение в ваш function. you верните мне 0! Ура, никакой радиации! Кроме того, что это действительно там, и это просто то, что я проходил в плохом value. but я понятия не имею. Я хочу, чтобы подразделение выбросило ошибку, потому что это флаг, что что-то не так.
Вы можете, по крайней мере, остановить разрыв запроса с ошибкой и вернуть NULL , если есть деление на ноль:
Однако я бы NEVER преобразовал это в ноль с coalesce , как показано в том другом ответе, который получил много апвотов. Это совершенно неверно в математическом смысле, и это даже опасно, поскольку ваше приложение, скорее всего, вернет неправильные и вводящие в заблуждение результаты.
Поймав ноль с nullif(), а затем полученный null с isnull(), вы можете обойти свое деление на нулевую ошибку.
Замена «divide by zero» на ноль спорна , но это также не единственный вариант. В некоторых случаях замена на 1 является (разумно) целесообразной. Я часто ловлю себя на том, что использую
когда я смотрю на сдвиги в scores/counts, и хочу по умолчанию установить значение 1, Если у меня нет данных. Например
Чаще всего я действительно рассчитывал это соотношение где-то в другом месте (не в последнюю очередь потому, что оно может привести к очень большим поправочным коэффициентам для низких знаменателей. В этом случае я бы обычно контролировал для OldSampleScore больше порога; который тогда исключает ноль. Но иногда ‘hack’ вполне подходит.
Некоторое время назад я написал функцию для обработки ее для своих хранимых процедур :
- Добавьте ограничение CHECK, которое заставляет Divisor быть ненулевым
- Добавьте в форму валидатор, чтобы пользователь не мог ввести в это поле нулевые значения.
Для обновления SQLs:
Вот такая ситуация, когда можно делить на ноль. Бизнес-правило заключается в том, что для расчета оборотов запасов вы берете себестоимость проданных товаров за определенный период, пересчитываете ее в год. После того как у вас есть годовой номер, вы делите его на средний запас за этот период.
Я рассматриваю расчет количества оборотов запасов, которые происходят в течение трехмесячного периода. Я рассчитал, что у меня есть стоимость товаров, проданных в течение трехмесячного периода $1,000. годовой темп продаж составляет $4,000 ($1,000/3)*12. начальный запас равен 0. Конечный инвентарь равен 0. Мой средний запас сейчас равен 0. У меня есть продажи $4000 в год,и никаких запасов. Это дает бесконечное число оборотов. Это означает, что все мои запасы преобразуются и покупаются клиентами.
Это бизнес-правило расчета оборотов запасов.
Нет никакой волшебной глобальной настройки «отключить деление на 0 исключений». Операция должна быть брошена, так как математическое значение x/0 отличается от значения NULL, поэтому она не может вернуть NULL. Я предполагаю, что вы заботитесь об очевидном, и ваши запросы имеют условия, которые должны исключить записи с делителем 0 и никогда не оценивать деление. Обычно ‘gotcha’-это то, что большинство разработчиков ожидают от SQL поведения процедурных языков и предложения логического оператора короткого замыкания, но это действительно так . Я рекомендую вам прочитать эту статью: http://www.sqlmag.com/Articles/ArticleID/9148/pg/2/2.html
Отфильтруйте данные с помощью предложения where, чтобы не получить 0 значений.
Иногда 0 может быть неуместным, но иногда 1 также неуместен. Иногда скачок от 0 до 100 000 000, описанный как 1 или 100-процентное изменение, также может ввести в заблуждение. 100 000 000 процентов может быть подходящим в этом сценарии. Это зависит от того, какие выводы вы собираетесь сделать на основе процентных соотношений или коэффициентов.
Например, очень мелкий продающий элемент, перемещающийся с 2-4 проданного, и очень крупный продающий элемент, изменяющийся с 1 000 000 до 2 000 000 проданного, могут означать очень разные вещи для аналитика или для руководства, но оба они будут проходить как 100% или 1 изменение.
Возможно, будет проще изолировать NULL значение, чем рыскать по куче 0% или 100% строк, смешанных с законными данными. Часто 0 в знаменателе может указывать на ошибку или пропущенное значение, и вы не можете просто заполнить произвольное значение, чтобы ваш набор данных выглядел аккуратно.
Вы можете соответствующим образом обработать ошибку, когда она распространяется обратно в вызывающую программу (или игнорировать ее, если это то, что вы хотите). В C# любые ошибки, возникающие в SQL, будут вызывать исключение, которое я могу поймать и затем обработать в своем коде, как и любую другую ошибку.
Я согласен с Бэской в том, что вы не хотите скрывать свою ошибку. Возможно, вы не имеете дело с ядерным реактором, но скрывать ошибки в целом-плохая практика программирования. Это одна из причин, по которой большинство современных языков программирования используют структурированную обработку исключений, чтобы отделить фактическое возвращаемое значение от кода ошибки / состояния. Это особенно верно, когда вы занимаетесь математикой. Самая большая проблема заключается в том, что вы не можете отличить правильно вычисленный 0, возвращаемый или 0 в результате ошибки. Вместо этого любое возвращаемое значение является вычисляемым значением, и если что-то идет не так, то создается исключение. Это, конечно, будет отличаться в зависимости от того, как вы получаете доступ к базе данных и какой язык вы используете, но вы всегда должны иметь возможность получить сообщение об ошибке, с которым вы можете иметь дело.
Используйте NULLIF(exp,0) , но таким образом — NULLIF(ISNULL(exp,0),0)
NULLIF(exp,0) ломается, если ехр null но NULLIF(ISNULL(exp,0),0) не сломается
Похожие вопросы:
Когда я выполняю свою хранимую процедуру, она бросает исключение Divide By zero. Потому что в моей базе данных нет данных за несколько месяцев. Как я могу решить эту проблему? Ниже приведен мой.
Как я могу поймать ошибку divide-by-zero (а не другие ошибки; и иметь возможность получить доступ к информации об исключениях) в Visual Studio 2008 C++? Я попробовал это сделать: try < int j=0; int.
В javascript, деление на ноль с аргументами integer действует как плавающие точки должны: 1/0; // Infinity -1/0; // -Infinity 0/0; // NaN Спецификация asm.js говорит, что деление с целочисленными.
Я использую bc, чтобы сделать серию вычислений. Я называю это скриптом bash, который сначала помещает все выражения, которые должны быть вычислены в одну переменную, передает их в bc для вычисления.
Я пытаюсь запустить скрипт в SQL, в котором я делюсь, но я получаю ошибку Divide by zero error encountered Я попытался добавить в NULLIF, что было предложено в старом посте, который я читал, но это.
У меня есть double[] , на котором выполняется операция LINQ: MD = MD.Select(n => n * 100 / MD.Sum()).ToArray(); В некоторых случаях все элементы MD равны 0, а затем Sum также равен нулю. Тогда 0.
Пожалуйста, обратите внимание на следующий код и комментарии: Console.WriteLine(1 / 0); // will not compile, error: Division by constant zero int i = 0; Console.WriteLine(1 / i); // compiles, runs.
Я пытаюсь понять прерывания в x86 assembly. Я попытался вызвать ошибку divide-by-zero, которая соответствует коду 0. int $0 Я ожидал, что это будет иметь такое же поведение, как деление на ноль.
У меня есть ошибка подходит Divide by zero error encountered. в SQL Server 2005. Я понимаю, что у меня есть несколько строк, которые делятся на ноль, что приводит к этой ошибке. Поэтому мне было.
Думаю, я понимаю, почему звоню glRotate(#, 0, 0, 0) в результате получается divide-by-zero. Вектор вращения, a, нормализуется: a’ = a/|a| = a / 0 Это единственная ситуация, в которой glRotate может.
Using NULLIF() To Prevent Divide-By-Zero Errors In SQL
Boyan Kostadinov just sent me a cool link to an article that is the final part in a four part series that discusses the SQL NULL value. I haven’t read the first three parts yet, but there is a really cool tip in the fourth part on using NULLIF() to prevent divide-by-zero errors in a SQL call.
The idea here is that, as with any other form of math that I know of, you cannot divide by zero in a SQL call. Therefore, running this code:
- SELECT
- ( 45 / 0 ) AS value
- ;
. results in a SQL error being thrown:
Error Executing Database Query. [Macromedia] [SQLServer JDBC Driver] [SQLServer] Divide by zero error encountered.
To prevent this sort of error from being thrown, author Hugo Kornelis suggests using a NULLIF() in the divisor of the equation. NULLIF() takes two arguments and returns NULL if the two values are the same and can be used to turn the divisor from a zero into a NULL which, in turn, will force the entire equation to become NULL. Therefore, running this code:
- SELECT
- ( 45 / NULLIF( 0, 0 ) ) AS value
- ;
- [ #qDivision.value# ]
. we get the following output:
Here, the NULLIF( 0, 0 ) returns NULL since zero is equal to zero, which gets the SQL statement to return NULL, which gets ColdFusion to show an empty string. This is a seemingly pointless example since both zero values are hard coded, but imagine if this were a user-entered value, or even better yet, a SQL aggregate or other calculated value (such as might be used in a report or data mining exercise).
Now, let’s say you want to take this one step further and provide a default value for the equation if NULL is encountered (A default value, though not entirely accurate might make your consuming code more compact as it won’t have to deal with exception cases). To set a default value, we could use the ISNULL() or COALESCE() functions:
- SELECT
- (
- ISNULL(
- (45 / NULLIF( 0, 0 )),
- )
- ) AS value
- ;
- [ #qDivision.value# ]
Here, we are performing the division as we were above, but then, if that equation returns NULL, our ISNULL() function is going to catch that and return zero as its default value. Therefore, running the above code, we get the following output:
As someone who runs a ton of reports on database table (albeit, not in any educated way), this is going to come in very handy. I find that in most cases, having a zero is graphically equivalent to NULL and a whole lot easier to deal with.
Enjoyed This? You Might Also Enjoy Reading:
Reader Comments
I’ve had this problem in strange statistics data for a long time and its always been a little bit tricky to over come, this is a nice solution, and its all done in SQL too.
In the past I’ve pulled the math out of SQL and had CF do it as I had more control over the devision by zero, this makes a hell of a lot more sense.
Yeah, I feel your pain. I used to use CASE statements in the divisor. It worked, but it was just wordy and distracting. I find this to be much more straight forward and readable.
Is this function specific to SQL Server or will it work on other databases as well? (Oracle, MySQL, etc.)
I think NULLIF() is standard. Not sure about ISNULL(). I think COALESCE() is more standard than ISNULL().
Excellent find! Wish I would have known about this a long time ago — I’ve always just used a case statement:
case
when isNull(divisor, 0) = 0
then 0
else numerator/divisor end as value
But this seems much nicer!
How about speed between case n nullif
I would guess that CASE would be faster only because it is inline rather than a method call. But, just a guess.
Could not be easier. Thanks a lot !!
For Oracle, you might try something like this: columnname1/decode(columnname2,0,null)
Thanks. This helped with a very tough calculation. Wasn’t even aware this function was out there.
Using this I soved my problem. For e.g
sum(objid)/nullif(count(units_purch),0)
where count(units_purch) return 0 value.
However I’ve one question can I solve this problem using CASE statement. If yes, then how?
Thanks in advance!
Yeah, the nullif() is really just a short hand for the CASE statement. CASE statements are powerful and can be used just about anywhere:
SUM( objid ) / (
CASE
WHEN COUNT( units_purch ) = 0
THEN NULL
ELSE COUNT( units_purch )
END
)
As you can see, NULLIF() is a lot easier (and prevents you from having to calculate count() twice.
I just updated my script with this code and it worked like a clock. This will save me gobs of time plus keep my code less complicated. Thanks a million! Rock On!
VERY late to the party here, but I had occasion to work on a Divide By Zero error today, and came across your post.
With MSSQL (2005 anyway) you can add these two lines ahead of the query that could potentially fail with a DBZ error:
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
With both ARITHABORT and ANSI_WARNINGS set to OFF, SQL Server will return a NULL value in a calculation involving a divide-by-zero error. To return a 0 value instead of a NULL value, you could still put the division operation inside the ISNULL function:
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
SELECT ISNULL([Numerator] / [Denominator], 0)
Just one more way to skin the cat. I would assume one would want to use this solution with care, especially when dealing with multiple queries in one request. experimentation is certainly in order.
Oh cool. I feel like with every SQL server release, they’re just adding more cool stuff. I’ve been using MySQL a lot lately and there’s even more stuff in there than I realize. I keep meaning to just read through the docs.
you’re my hero! goodbye forever, stupid ugly CASE method
Watch it. NULLIF in SQL SERVER 2000 is buggy!
SELECT ISNULL(NULLIF(», »), 6)
gives: *
SELECT ISNULL(NULLIF(», »), ‘abc’)
gives: empty string
thanks for all good notes
Thanks for this, over the last couple of years I find myself coming back to this page to look at how to avoid this problem.
I’m attempting to use this feature when calculating the average for a value, but I’m not certain if my syntax is correct as CF throws an error:
avg (isNull((((docunitprice * orderqty)-((c.avglaborcost + c.avgburdencost + c.avgmaterialcost + c.avgsubcontcost + c.avgmtlburcost)*d.orderqty))/ nullif(docunitprice * orderqty),0))) as PercValueAdd
Does this work within a function?
hi.. I am facing a problem. I have a online form. when I fill this form and submit. my form submited well without any error. but when I went to the C-Panel for to check and Grab out this form data. I am finding values 0,0,0,0 in all fields.for example.
I have 6 fields created in my form.
1 NAME 2.CITY NAME 3.E-mail id 4.Contact No 5.Pass and 6.Comments Area in my form. but when I go the C-panel for to get out the data from above field after completing form. I received values 0,0,0,0,0, in all fields. please help me out.
This has been bugging me for soo long! A full hour of crunching stopped becuase of a 0 on a single row..
Nice! I was looking for a solution solving divide by zero problem without using case (the query was already too complex) and this is THE solution!
Nice article and useful tip.
However, slightly concerned about your concluding remark: . in most cases, having a zero is graphically equivalent to NULL and a whole lot easier to deal with.
In general, it is statistical best practice to distinguish between zeros and nulls because very often they mean two very different things. Consider a situation in which 0 is bad and non-zero is good. Management is interested in the percentage of zeros out of the total number of cases. Typically, no one thinks to specify that nulls should be excluded. But encountering the nulls prompts the question. By automatically letting 0 be the default for nulls you are introducing potentially quite significant bias into your data sets.
So, without labouring the point, I recommend that you reconsider this last line, if only to remove it from an article that others might model their own data processing behaviour on.
Hi, I have a problem, the query below gives me zero value. please help.
In case when divisor could be NULL it’s important to NVL it to ZERO. At least Oracle’s implementation of NULLIF doesn’t accept NULL value as valid parameter and returns error message about it.
So, in complete form it looks like:
NVL will change NULL on 0 and NULLIF will change all zeroes to NULL without failures.
bennadel.com saves me again!
Well done. Thank you.
good article.
colsec() method has better result than Isnull()..
so in place of Isnull() method use Colsec()method.
it is more standard and recommended by Microsoft Sql Server .
Thanking you
—
Mohammad Shahnawaz
India
I guess you meant COALESCE() which is mentioned in the article. Yes, it’s more widely implemented while Oracle uses NVL instead of ISNULL but each function have own purpose. COALESCE is more complex function and capable to accept any number of parameters while isnull/nvl are tailored to replace NULL value from one single column with something different and do it as fast as possible. When you have to deal with billions of records in one query it could be important.
Thank you, great article thanks for sharing .
SQLShack
Methods to avoid the SQL divide by zero error
This article explores the SQL divide by zero error and various methods for eliminating this.
Introduction
We all know that in math, it is not possible to divide a number by zero. It leads to infinity:
If you try to do in calculator also, you get the error message – Cannot Divide by zero:
We perform data calculations in SQL Server for various considerations. Suppose we perform an arithmetic division operator for calculating a ratio of products in a store. Usually, the division works fine, and we get the ratio:
Someday, the product2 quantity goes out of stock and that means we do not have any quantity for product2. Let’s see how the SQL Server query behaves in this case:
We get SQL divide by zero error messages (message id 8134, level 16):
We do not want our code to fail due to these errors. It is a best practice to write code in such a way that it does not give divide by zero message. It should have a mechanism to deal proactively with such conditions.
SQL Server provides multiple methods for avoiding this error message. Let’s explore it in the next section.
Method 1: SQL NULLIF Function
We use NULLIF function to avoid divide by zero error message.
The syntax of NULLIF function:
It accepts two arguments.
If both the arguments are equal, it returns a null value
For example, let’s say both arguments value is 10:
In the screenshot, we can see that the output is null:
If both the arguments are not equal, it returns the value of the first argument
In this example, both argument values differ. It returns the output as value of first argument 10:
Let’s modify our initial query using the SQL NULLIF statement. We place the following logic using NULLIF function for eliminating SQL divide by zero error:
- Use NULLIF function in the denominator with second argument value zero
- If the value of the first argument is also, zero, this function returns a null value. In SQL Server, if we divide a number with null, the output is null as well
- If the value of the first argument is not zero, it returns the first argument value and division takes place as standard values
Execute this modified query. We can see the output NULL because denominator contains value zero.
Do we want null value in the output? Is there any method to avoid null and display a definite value?
Yes, we can use SQL ISNULL function to avoid null values in the output. This function replaces the null value in the expression1 and returns expression2 value as output.
Let’s explore the following query with a combination of SQL NULLIF and SQL ISNULL function:
- First argument ((@Product1 / NULLIF(@Product2,0)) returns null
- We use the ISNULL function and specify the second argument value zero. As we have the first argument null, the output of overall query is zero (second argument value)
Method 2: Using CASE statement to avoid divide by zero error
We can use a CASE statement in SQL to return values based on specific conditions. Look at the following query. It does the following task with the Case statement.
The Case statement checks for the value of @Product2 parameter:
- If the @Product2 value is zero, it returns null
- If the above condition is not satisfied, it does the arithmetic operation (@Product1/@Product2) and returns the output
Method 3: SET ARITHABORT OFF
We can use set methods to control query behavior. By default, SQL Server has a default value of SET ARITHABORT is ON. We get SQL divide by zero error in the output using the default behavior.
The T-SQL syntax for controlling the ARITHABORT option is shown below:
Using ARITHABORT ON, the query will terminate with divide by zero message. It is the default behavior. For this demo, let’s enable it using the SET ARITHABORT ON statement:
We get the SQL divide by zero error messages:
Using ARITHABORT OFF, the batch will terminate and returns a null value. We need to use ARITHABORT in combination with SET ANSI_WARNINGS OFF to avoid the error message:
We can use the following query to check the current setting for the ARITHABORT parameter:
The default ARITHABORT setting for SSMS is ON. We can view it using SSMS Tools properties. Navigate to Tools -> Options -> Advanced:
Many client applications or drivers provide a default value of ARITHABORT is OFF. The different values might force SQL Server to produces a different execution plan, and it might create performance issues. You should also match the setting similar to a client application while troubleshooting the performance issues.
Note: You should not modify the value of ARITHABORT unless required. It might create performance issues, as well. I would suggest using alternative methods (as described earlier) for avoiding SQL divide by zero error.
Conclusion
In this article, we explored the various methods for avoiding SQL divide by zero error. It is best practice to be proactive and use these mechanisms so that code does not fail in real-time.
Rajendra has 8+ years of experience in database administration having a passion for database performance optimization, monitoring, and high availability and disaster recovery technologies, learning new things, new features.
Как избежать ошибки «деление на ноль» в SQL?
У меня есть это сообщение об ошибке:
Msg 8134, Уровень 16, состояние 1, Линия 1 делится на нулевую ошибку.
каков наилучший способ написать код SQL, чтобы я больше никогда не видел это сообщение об ошибке?
Я мог бы сделать одно из следующих действий:
- добавьте предложение where, чтобы мой делитель никогда не был равен нулю
- я мог бы добавить оператор case, так что есть особое отношение к нулю.
— лучший способ использовать NULLIF предложения?
есть ли лучший способ, или как это может быть реализовано?
17 ответов
чтобы избежать ошибки «деление на ноль», мы запрограммировали ее следующим образом:
но вот гораздо более приятный способ сделать это:
теперь единственная проблема-запомнить бит NullIf, если я использую ключ»/».
Если вы хотите вернуть ноль, в случае, если произойдет нулевое деление, вы можете использовать:
для каждого делителя, который равен нулю, вы получите ноль в результирующем наборе.
это казалось лучшим решением для моей ситуации при попытке решить деление на ноль, что происходит в моих данных.
Предположим, вы хотите рассчитать соотношение мужчин и женщин для различных школьных клубов, но вы обнаружите, что следующий запрос терпит неудачу и выдает ошибку деления на ноль, когда он пытается рассчитать соотношение для клуба «Властелин колец», в котором нет женщин:
вы можете использовать функцию NULLIF чтобы избежать деления на ноль. NULLIF сравнивает два выражения и возвращает нуль, если они равны или первое выражение в противном случае.
переписать запрос так:
любое число, разделенное на NULL дает NULL , и ошибка не генерируется.
вы также можете сделать это в начале запрос:
Так что если у вас есть что-то вроде 100/0 он вернет значение NULL. Я сделал это только для простых запросов, поэтому я не знаю, как это повлияет на более длинные/сложные.
изменить: Я получаю много downvotes на этом недавно. поэтому я подумал, что просто добавлю примечание, что этот ответ был написан до того, как вопрос прошел последнее редактирование, где возврат null был выделен как опция. что кажется вполне приемлемым. Некоторые из моих ответов были адресованы таким проблемам, как Эдвардо, в комментариях, который, казалось, выступал за возвращение 0. Это тот случай, против которого я выступал.
ответ: Я думаю, что здесь есть основная проблема, то есть деление на 0 не является законным. Это признак того, что что-то фундаментально неправильно. Если вы делите на ноль, вы пытаетесь сделать что-то, что не имеет смысла математически, поэтому никакой числовой ответ, который вы можете получить, не будет действительным. (Использование null в этом случае разумно, так как это не значение, которое будет использоваться в последующих математических расчетах).
поэтому Эдвардо спрашивает в комментариях: «что, если пользователь ставит 0?», и он выступает за то, чтобы получить 0 в ответ. Если пользователь помещает ноль в сумму, и вы хотите, чтобы 0 возвращалось, когда они это делают, то вы должны ввести код на уровне бизнес-правил, чтобы поймать это значение и вернуть 0. не имеют особого случая, когда деление на 0 = 0.
Это тонкая разница, но это важно. потому что в следующий раз, когда кто-то вызывает вашу функцию и ожидает, что она сделает правильную вещь, и она делает что-то фанки, что не является математически правильным, а просто обрабатывает конкретный случай edge у него есть хороший шанс укусить кого-нибудь позже. На самом деле вы не делите на 0. ты просто возвращаешь плохой ответ на плохой вопрос.
представьте, что я что-то кодирую, и я все испортил. Я должен был бы читать в значении масштабирования измерения излучения, но в странном случае края я не ожидал, я читал в 0. Затем я опускаю свою ценность в вашу функцию. ты возвращаешь мне ноль! Ура, никакой радиации! За исключением того, что это действительно там, и это просто то, что я передавал плохую ценность. но я понятия не иметь. Я хочу, чтобы подразделение выбросило ошибку, потому что это флаг, что что-то не так.
вы можете, по крайней мере, остановить запрос от разрыва с ошибкой и вернуть NULL если есть деление на ноль:
, Я никогда преобразовать это в ноль с coalesce как показано в другой ответ, который получил много положительных отзывов. Это совершенно неправильно в математическом смысле, и это даже опасно, поскольку ваше приложение, вероятно, вернет неправильные и вводящие в заблуждение результаты.
поймав ноль с nullif (), то результирующий null с isnull () вы можете обойти свое деление на нулевую ошибку.
замена «деления на ноль» на ноль является спорной, но это также не единственный вариант. В некоторых случаях замена на 1 (разумно) уместна. Я часто нахожу себя с помощью
когда я смотрю на сдвиги в баллах / подсчетах и хочу по умолчанию 1, Если у меня нет данных. Например
чаще всего я фактически рассчитал это соотношение где-то еще (не в последнюю очередь потому, что он может бросить некоторые очень большие коэффициенты регулировки для низких знаменатели. В этом случае я обычно контролирую для OldSampleScore больше порога; который затем исключает ноль. Но иногда «взлом» уместен.
Using NULLIF() To Prevent Divide-By-Zero Errors In SQL
Boyan Kostadinov just sent me a cool link to an article that is the final part in a four part series that discusses the SQL NULL value. I haven’t read the first three parts yet, but there is a really cool tip in the fourth part on using NULLIF() to prevent divide-by-zero errors in a SQL call.
The idea here is that, as with any other form of math that I know of, you cannot divide by zero in a SQL call. Therefore, running this code:
- SELECT
- ( 45 / 0 ) AS value
- ;
. results in a SQL error being thrown:
Error Executing Database Query. [Macromedia] [SQLServer JDBC Driver] [SQLServer] Divide by zero error encountered.
To prevent this sort of error from being thrown, author Hugo Kornelis suggests using a NULLIF() in the divisor of the equation. NULLIF() takes two arguments and returns NULL if the two values are the same and can be used to turn the divisor from a zero into a NULL which, in turn, will force the entire equation to become NULL. Therefore, running this code:
- SELECT
- ( 45 / NULLIF( 0, 0 ) ) AS value
- ;
- [ #qDivision.value# ]
. we get the following output:
Here, the NULLIF( 0, 0 ) returns NULL since zero is equal to zero, which gets the SQL statement to return NULL, which gets ColdFusion to show an empty string. This is a seemingly pointless example since both zero values are hard coded, but imagine if this were a user-entered value, or even better yet, a SQL aggregate or other calculated value (such as might be used in a report or data mining exercise).
Now, let’s say you want to take this one step further and provide a default value for the equation if NULL is encountered (A default value, though not entirely accurate might make your consuming code more compact as it won’t have to deal with exception cases). To set a default value, we could use the ISNULL() or COALESCE() functions:
- SELECT
- (
- ISNULL(
- (45 / NULLIF( 0, 0 )),
- )
- ) AS value
- ;
- [ #qDivision.value# ]
Here, we are performing the division as we were above, but then, if that equation returns NULL, our ISNULL() function is going to catch that and return zero as its default value. Therefore, running the above code, we get the following output:
As someone who runs a ton of reports on database table (albeit, not in any educated way), this is going to come in very handy. I find that in most cases, having a zero is graphically equivalent to NULL and a whole lot easier to deal with.
Enjoyed This? You Might Also Enjoy Reading:
Reader Comments
I’ve had this problem in strange statistics data for a long time and its always been a little bit tricky to over come, this is a nice solution, and its all done in SQL too.
In the past I’ve pulled the math out of SQL and had CF do it as I had more control over the devision by zero, this makes a hell of a lot more sense.
Yeah, I feel your pain. I used to use CASE statements in the divisor. It worked, but it was just wordy and distracting. I find this to be much more straight forward and readable.
Is this function specific to SQL Server or will it work on other databases as well? (Oracle, MySQL, etc.)
I think NULLIF() is standard. Not sure about ISNULL(). I think COALESCE() is more standard than ISNULL().
Excellent find! Wish I would have known about this a long time ago — I’ve always just used a case statement:
case
when isNull(divisor, 0) = 0
then 0
else numerator/divisor end as value
But this seems much nicer!
How about speed between case n nullif
I would guess that CASE would be faster only because it is inline rather than a method call. But, just a guess.
Could not be easier. Thanks a lot !!
For Oracle, you might try something like this: columnname1/decode(columnname2,0,null)
Thanks. This helped with a very tough calculation. Wasn’t even aware this function was out there.
Using this I soved my problem. For e.g
sum(objid)/nullif(count(units_purch),0)
where count(units_purch) return 0 value.
However I’ve one question can I solve this problem using CASE statement. If yes, then how?
Thanks in advance!
Yeah, the nullif() is really just a short hand for the CASE statement. CASE statements are powerful and can be used just about anywhere:
SUM( objid ) / (
CASE
WHEN COUNT( units_purch ) = 0
THEN NULL
ELSE COUNT( units_purch )
END
)
As you can see, NULLIF() is a lot easier (and prevents you from having to calculate count() twice.
I just updated my script with this code and it worked like a clock. This will save me gobs of time plus keep my code less complicated. Thanks a million! Rock On!
VERY late to the party here, but I had occasion to work on a Divide By Zero error today, and came across your post.
With MSSQL (2005 anyway) you can add these two lines ahead of the query that could potentially fail with a DBZ error:
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
With both ARITHABORT and ANSI_WARNINGS set to OFF, SQL Server will return a NULL value in a calculation involving a divide-by-zero error. To return a 0 value instead of a NULL value, you could still put the division operation inside the ISNULL function:
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
SELECT ISNULL([Numerator] / [Denominator], 0)
Just one more way to skin the cat. I would assume one would want to use this solution with care, especially when dealing with multiple queries in one request. experimentation is certainly in order.
Oh cool. I feel like with every SQL server release, they’re just adding more cool stuff. I’ve been using MySQL a lot lately and there’s even more stuff in there than I realize. I keep meaning to just read through the docs.
you’re my hero! goodbye forever, stupid ugly CASE method
Watch it. NULLIF in SQL SERVER 2000 is buggy!
SELECT ISNULL(NULLIF(», »), 6)
gives: *
SELECT ISNULL(NULLIF(», »), ‘abc’)
gives: empty string
thanks for all good notes
Thanks for this, over the last couple of years I find myself coming back to this page to look at how to avoid this problem.
I’m attempting to use this feature when calculating the average for a value, but I’m not certain if my syntax is correct as CF throws an error:
avg (isNull((((docunitprice * orderqty)-((c.avglaborcost + c.avgburdencost + c.avgmaterialcost + c.avgsubcontcost + c.avgmtlburcost)*d.orderqty))/ nullif(docunitprice * orderqty),0))) as PercValueAdd
Does this work within a function?
hi.. I am facing a problem. I have a online form. when I fill this form and submit. my form submited well without any error. but when I went to the C-Panel for to check and Grab out this form data. I am finding values 0,0,0,0 in all fields.for example.
I have 6 fields created in my form.
1 NAME 2.CITY NAME 3.E-mail id 4.Contact No 5.Pass and 6.Comments Area in my form. but when I go the C-panel for to get out the data from above field after completing form. I received values 0,0,0,0,0, in all fields. please help me out.
This has been bugging me for soo long! A full hour of crunching stopped becuase of a 0 on a single row..
Nice! I was looking for a solution solving divide by zero problem without using case (the query was already too complex) and this is THE solution!
Nice article and useful tip.
However, slightly concerned about your concluding remark: . in most cases, having a zero is graphically equivalent to NULL and a whole lot easier to deal with.
In general, it is statistical best practice to distinguish between zeros and nulls because very often they mean two very different things. Consider a situation in which 0 is bad and non-zero is good. Management is interested in the percentage of zeros out of the total number of cases. Typically, no one thinks to specify that nulls should be excluded. But encountering the nulls prompts the question. By automatically letting 0 be the default for nulls you are introducing potentially quite significant bias into your data sets.
So, without labouring the point, I recommend that you reconsider this last line, if only to remove it from an article that others might model their own data processing behaviour on.
Hi, I have a problem, the query below gives me zero value. please help.
In case when divisor could be NULL it’s important to NVL it to ZERO. At least Oracle’s implementation of NULLIF doesn’t accept NULL value as valid parameter and returns error message about it.
So, in complete form it looks like:
NVL will change NULL on 0 and NULLIF will change all zeroes to NULL without failures.
bennadel.com saves me again!
Well done. Thank you.
good article.
colsec() method has better result than Isnull()..
so in place of Isnull() method use Colsec()method.
it is more standard and recommended by Microsoft Sql Server .
Thanking you
—
Mohammad Shahnawaz
India
I guess you meant COALESCE() which is mentioned in the article. Yes, it’s more widely implemented while Oracle uses NVL instead of ISNULL but each function have own purpose. COALESCE is more complex function and capable to accept any number of parameters while isnull/nvl are tailored to replace NULL value from one single column with something different and do it as fast as possible. When you have to deal with billions of records in one query it could be important.
Thank you, great article thanks for sharing .