В чем смысл DBNull?

В .NET есть ссылка null, которая везде используется для обозначения того, что ссылка на объект пуста, а затем есть DBNull, которая используется драйверами базы данных (и некоторыми другими) для обозначения... почти одного и того же. . Естественно, это создает много путаницы, и приходится штамповать процедуры преобразования и т. д.

Так почему же первоначальные авторы .NET решили сделать это? Для меня это не имеет смысла. Их документация также не имеет смысла:

Класс DBNull представляет несуществующее значение. Например, в базе данных столбец в строке таблицы может вообще не содержать никаких данных. То есть считается, что столбец вообще не существует, а не просто не имеет значения. Объект DBNull представляет несуществующий столбец. Кроме того, COM-взаимодействие использует класс DBNull, чтобы различать вариант VT_NULL, указывающий на несуществующее значение, и вариант VT_EMPTY, указывающий на неуказанное значение.

Что это за хрень про "столбец не существует"? Столбец существует, просто в нем нет значения для конкретной строки. Если бы его не было, я бы получил исключение при попытке доступа к конкретной ячейке, а не DBNull! Я могу понять необходимость различать VT_NULL и VT_EMPTY, но тогда почему бы вместо этого не создать класс COMEmpty? Это было бы гораздо лучше вписано во всю структуру .NET.

Я что-то упускаю? Может ли кто-нибудь пролить свет, почему был изобретен DBNull и какие проблемы он помогает решить?


person Vilx-    schedule 20.12.2010    source источник
comment
Еще одна точка данных... модуль DBI (интерфейс базы данных) в языке Perl не имеет концепции DbNull. Когда значение в базе данных равно NULL, DBI представляет его как Perl undef, который является Perl-эквивалентом null в C#. Итак, Perl занял позицию, согласно которой в специальной концепции DbNull нет необходимости, и я не слышал ни о каких Perl-программистах, которые хотели бы иметь DbNull.   -  person JoelFan    schedule 12.10.2011
comment
Я с тобой, @JoelFan - я тоже не вижу в этом никакой пользы   -  person Marc Gravell    schedule 09.03.2012
comment
Помимо ответов ниже, очень важен комментарий @thomas-levesque ниже: DBNull предшествует введению в .NET framework подлинных типов, допускающих значение NULL. Оба ведут себя немного иначе, поэтому DBNull пришлось остаться (к моему сожалению, но это уже другая история).   -  person Jeroen Wiert Pluimers    schedule 09.03.2013
comment
Мне нравится вопрос, но должен сказать, что сообщество непоследовательно. Много вопросов почему так? быть закрытым как не вопрос, особенно если спрашивающий позволяет себе объяснить, почему что-то кажется бессмысленным. (Я пытался спрашивать/жаловаться на отсутствие надлежащей поддержки абстрактных типов при представлении сервисов WCF в качестве веб-сервисов, и меня тут же застрелили!)   -  person The Dag    schedule 02.05.2013


Ответы (6)


Дело в том, что в определенных ситуациях существует разница между значением базы данных, равным нулю, и значением .NET Null.

Например. Если вы используете ExecuteScalar (который возвращает первый столбец первой строки в результирующем наборе) и получаете нулевое значение, это означает, что выполненный SQL не вернул никаких значений. Если вы получите обратно DBNull, это означает, что значение было возвращено SQL, и оно было NULL. Вы должны быть в состоянии сказать разницу.

person Colin Mackay    schedule 20.12.2010
comment
Хорошо, это один хороший пример, я полагаю. Хотя одной причины недостаточно, чтобы оправдать весь этот бардак. ExecuteScalar можно было бы переписать по-другому, чтобы решить эту конкретную проблему (DBEmptyRowset, кто-нибудь?) - person Vilx-; 20.12.2010
comment
Я доволен тем, как Microsoft написала ADO.NET. Использование DBNull обеспечивает согласованность всего. Каждый раз, когда значение столбца равно null, вы получаете DBNull. Конечно, код для обработки этого может быть немного более громоздким, чем простой возвращаемый null, особенно если все, что вы делаете, это конвертируете DBNull в null, но в конце дня согласованность является ключевым моментом. Если бы они изменили ExecuteScalar, потому что вам нужно указать разницу в этом сценарии, это вызвало бы гораздо большее раздражение. Конечно, это всего лишь мое мнение. - person Colin Mackay; 20.12.2010
comment
Изменение одного метода ExecuteScalar() вместо изменения всех поставщиков БД, наборов данных/таблиц/строк/столбцов, элементов управления с привязкой к данным и чего-то еще? Я бы пошел за первым. В конце концов, это сделало бы весь код НАМНОГО более последовательным. И простой. Кроме того, ExecuteScalar является одним из наименее используемых методов в поставщиках данных. ›90% случаев приходится на DataReader. Кроме того, вы действительно думаете, что bool ExecuteScalar(out object Value) будет настолько непоследовательным? - person Vilx-; 20.12.2010
comment
@Blam - Хорошо, я тоже удалил свой. :) Во всяком случае, я не думаю, что вам нужно беспокоиться. DBNull и старые API никуда не денутся — от них зависит слишком много кода. :) - person Vilx-; 04.09.2013
comment
@Vilx- вы действительно думаете, что логическое значение ExecuteScalar (out object Value) будет таким непоследовательным? Нет, но это также раздражает. Все, что имеет параметр out jars. Но опять же, С# плохо обрабатывает кортежи (я думаю, что это немного упущение языка) - person Colin Mackay; 12.12.2013
comment
@ColinMackay - Ах, старые обиды. :) Паттерн bool/out согласуется со словарями, поэтому я изначально выбрал именно его. В качестве альтернативы он может просто вернуть object, а затем создать специальное значение для пустого набора строк, а не специальное значение для пустого значения. Или, может быть, вернуть null и иметь необязательный параметр out bool, потому что в большинстве случаев вас не волнует случай с пустым набором строк. - person Vilx-; 12.12.2013
comment
@Vilx- Хотя это немного противоречит названию метода, ExecuteScalar также может возвращать IEnumerable<object> с одним или нулевым значением. - person IS4; 14.07.2015
comment
Они могли просто вернуть ScalarResult со свойствами HasValue и Value. Нет веской причины для того, чтобы многие другие методы возвращали DBNull вместо null. Это просто плохой дизайн. - person Lukazoid; 14.10.2015
comment
Есть много вещей, которые они могли бы сделать. Но что сделано, то сделано, и Microsoft должна поддерживать его, чтобы гарантировать, что все существующие приложения, в которых он есть, не сломаются. - person Colin Mackay; 14.10.2015
comment
Лично я предпочел бы, чтобы ExecuteScalar генерировал исключение (DbException), если не было возвращаемого значения (нет строк или столбцов), и использовал null вместо DBNull - person Robert McKee; 11.07.2016
comment
@ColinMackay Хорошо, что вы сказали в своем ответе. но не является ли основное различие между DBNULL и .NET null; DBNULL — это HardDisk NULL. NET null — это Memory NULL. Поскольку HarDisk выделяет место для записи, даже если там ничего нет, но память не выделяет место для нулевого указателя, поскольку он не ссылается ни на какой адрес кучи; - person UfukSURMEN; 21.12.2016
comment
@UfukSURMEN Я не понимаю, что вы имеете в виду - и память, и жесткий диск являются носителями информации (хотя один более эфемерный, чем другой), так что в этом отношении нет никакой разницы. Если строка существует, то значение для столбца в этой строке может возвращать DBNULL, чтобы указать, что столбец для этой строки не имеет значения. Для ExecuteScalar NULL означает, что ни одна строка не была возвращена, а DBNULL означает, что была возвращена хотя бы одна строка, но первый столбец не имеет значения. - person Colin Mackay; 22.12.2016

Я собираюсь не согласиться с тенденцией здесь. Я сделаю запись:

Я не согласен с тем, что DBNull служит какой-либо полезной цели; это вносит ненужную путаницу, но практически не приносит пользы.

Часто выдвигается аргумент, что null — недопустимая ссылка, а DBNull — шаблон нулевого объекта; ни одно из них не верно. Например:

int? x = null;

это не "неверная ссылка"; это значение null. Действительно, null означает все, что вы хотите, и, честно говоря, у меня нет абсолютно никаких проблем с работой со значениями, которые могут быть null (действительно, даже в SQL нам нужно правильно работать с null - здесь ничего не меняется). Точно так же «шаблон нулевого объекта» имеет смысл только в том случае, если вы на самом деле рассматриваете его как объект в терминах ООП, но если у нас есть значение, которое может быть «нашим значением или DBNull», тогда оно должно быть object, поэтому мы можем не делайте с ним ничего полезного.

С DBNull так много плохого:

  • это заставляет вас работать с object, так как только object может содержать DBNull или другое значение
  • нет реальной разницы между "может быть значением или DBNull" и "может быть значением или null"
  • аргумент, что это происходит из 1.1 (pre-nullable-types), бессмысленен; мы могли бы прекрасно использовать null в 1.1
  • у большинства API есть «это нуль?» методы, например DBDataReader.IsDBNull или DataRow.IsNull - ни один из них на самом деле не требует существования DBNull с точки зрения API
  • DBNull терпит неудачу с точки зрения объединения с нулевым значением; value ?? defaultValue не работает, если значение равно DBNull
  • DBNull.Value нельзя использовать в необязательных параметрах, так как это не константа
  • семантика времени выполнения DBNull идентична семантике null; в частности, DBNull на самом деле равно DBNull, поэтому оно не выполняет работу по представлению семантики SQL
  • он часто принудительно упаковывает значения типа значения, поскольку он чрезмерно использует object
  • если вам нужно проверить на DBNull, вы могли бы также протестировать только на null
  • это вызывает огромные проблемы для таких вещей, как параметры команды, с очень глупым поведением, что если параметр имеет значение null, он не отправляется... ну, вот идея: если вы не хотите, чтобы параметр был отправлен - не добавлять его в коллекцию параметров
  • каждая ORM, о которой я могу думать, отлично работает без какой-либо потребности или использования DBNull, за исключением дополнительной неприятности при общении с кодом ADO.NET.

Единственный даже отдаленно убедительный аргумент, который я когда-либо видел для оправдания существования такого значения, находится в DataTable, при передаче значений для создания новый ряд; null означает "использовать значение по умолчанию", DBNull явно является нулем - честно говоря, этот API мог бы иметь особую обработку для этого случая - например, воображаемый DataRow.DefaultValue был бы намного лучше, чем ввод DBNull.Value, который заражает обширные участки кода бесплатно. причина.

Точно так же сценарий ExecuteScalar... в лучшем случае незначителен; если вы выполняете скалярный метод, вы ожидаете результата. В сценарии, где строк нет, возврат null не кажется таким уж ужасным. Если вам абсолютно необходимо устранить неоднозначность между «нет строк» ​​и «возвращается один единственный нуль», есть API-интерфейс для чтения.

Этот корабль уже давно уплыл, и слишком поздно его чинить. Но! Пожалуйста, не думайте, что все согласны с тем, что это "очевидно". Многие разработчики не видят ценность в этой странной морщинке в BCL.

Мне на самом деле интересно, связано ли все это с двумя вещами:

  • необходимость использовать слово Nothing вместо чего-то, включающего "null" в VB
  • имея возможность использовать синтаксис if(value is DBNull), который «выглядит точно так же, как SQL», а не такой хитрый if(value==null)

Резюме:

Наличие 3 вариантов (null, DBNull или фактическое значение) полезно только в том случае, если есть подлинный пример, в котором вам нужно устранить неоднозначность между 3 разными случаями. Мне еще предстоит увидеть случай, когда мне нужно представить два разных «нулевых» состояния, поэтому DBNull совершенно избыточен, учитывая, что null уже существует и имеет гораздо лучшую поддержку языка и среды выполнения.

person Marc Gravell    schedule 09.03.2012
comment
+1, у меня никогда не было ситуации, когда я действительно хотел, чтобы DBNull.Value отличался от нуля. Я всегда чувствовал, что это проблема, и видел (+ испытал) много времени, потраченного впустую из-за того, что null != DBNull.Value - person AdaTheDev; 09.03.2012
comment
Есть ли опечатка в DBNull на самом деле равно DBNull, если нет - я не понимаю :). Разве это не должно быть DBNull на самом деле равным нулю? - person Alex; 09.03.2012
comment
@ Алекс нет, нет опечатки; и DBNull определенно не равно нулю; попробуй bool x = DBNull.Value.Equals(DBNull.Value); bool y = DBNull.Value.Equals(null);. Я пытался подчеркнуть, что если вы попробуете это в базе данных SQL, совместимой с ANSI, вы обнаружите, что null не равно null (но в то же время null не равно null) - person Marc Gravell; 09.03.2012
comment
Спасибо за внимание, мне просто интересно, есть ли случай, когда DBNull НЕ является DBNull (в контексте ADO.NET). Немного смутил меня. - person Alex; 09.03.2012
comment
(перенесено из stackoverflow.com/questions/4958379/, кстати, показалось лучше) - person Marc Gravell; 09.03.2012
comment
Я думаю, что Nothing в VB.Net близок к отметке. Nothing Vb.Net не является прямым эквивалентом null C# (это более близкое совпадение для default(T)) и, следовательно, не может заполнить для VB.Net каждую функцию, которую вы предлагаете null лучше выполнить по сравнению с DBNull.Value в C#. Но да: DBNull.Value отстой. Я хотел бы, чтобы команда CLR реализовала какое-то автоматическое преобразование, поэтому, если вы передаете null в методы API ado.net, где допустимо только DBNull.Value (или устанавливаете его как значение параметра, например), он делает конвертация для вас. - person Joel Coehoorn; 09.03.2012
comment
Я нахожу ваш текст действительно запутанным, когда вы продолжаете говорить о «нулевых значениях» (было ли когда-либо значение null значением? Мой мозг продолжает говорить «нет» ...) и «значениях» DBNull: DBNull - это тип данных. Поэтому писать, что объект может содержать значение DBNull, для меня совершенно непонятно! - person Philippe Grondier; 28.12.2012
comment
@Philippe переменная имеет значение. Значение переменной может быть нулевым (для ссылочных типов, включая object, и для допускающих значение NULL--of-T). Да, ноль — это значение. В случае переменных ссылочного типа это полностью нулевая ссылка (хотя технически многие ненулевые ссылки с низким значением также будут интерпретироваться как нулевые в некоторых сценариях из-за деталей реализации). Переменная object может содержать ссылку на экземпляр DBNull; последнее, может быть, я и сократил, но не думаю, что смысл потерян. - person Marc Gravell; 29.12.2012
comment
@Марк, спасибо за твой ответ. В моей идее (и я думаю, что она довольно распространена, когда мы говорим о математике), понятие стоимости не существует вне основного понятия сравнения. Поскольку нули нельзя сравнивать, их нельзя упорядочивать, добавлять и т. д., их нельзя называть «значениями». На самом деле Null — это представление об отсутствии ценности. Тем не менее, эта концепция не реализована строго в компьютерных языках, где распространены такие приближения, как (сравнение), если my_x = null или (присваивание)x = null. Таким образом, мы могли бы сказать, что когда дело доходит до компьютерных наук, null — это значение... но мне это не нравится! - person Philippe Grondier; 29.12.2012
comment
@Philippe Филипп Я говорю о программировании, поэтому значение null - это просто последовательность битов, представляющая концепцию null, которая, кстати, в контексте объекта просто не является объектом. Термин null перегружен, и это не математическое использование. Хотя на самом деле концепция нулевого значения на самом деле не встречается в большинстве математических наук. - person Marc Gravell; 29.12.2012
comment
Может быть, DBNull был введен для того, чтобы иметь тип CLR с той же семантикой, что и нулевые значения базы данных? Напомним, что null не равен чему-либо, включая null, в реляционных базах данных, так что, например, выбор чего-то, где Col1 = Col2, не соответствует тому, где оба столбца не имеют значения. Null действительно не предназначен для представления значения, а не для использования в качестве магического значения. Говорить о том, какой битовый шаблон используется для представления понятия не имеет значения, означает полностью упускать суть. - person The Dag; 02.05.2013
comment
@Dag Я прокомментировал это: если это было намерением, оно терпит неудачу, как обсуждалось в моем ответе. - person Marc Gravell; 02.05.2013
comment
@ Марк Теперь я вижу, что ты это сделал, по семантике. А вот второй пункт стоит (параметры со значениями по умолчанию). Здесь у нас есть ситуация, когда это может быть мое значение, DBNull или CLR null, последнее означает использование значения по умолчанию. Конечно, последнего можно добиться и другими способами (например, опустив параметр), но я не думаю, что это было бы логично. Не сказать, что DBNull — это хорошо; Я просто не уверен, что это плохо. - person The Dag; 02.05.2013
comment
Проверка на наличие IsDBNull — это просто то, что я принял. Внешнее соединение может привести к отсутствию значения. Может быть некоторая оптимизация, чтобы не создавать нулевое значение. Я, вероятно, слишком много доверяю Reader, но может быть более эффективно возвращать IsDBNull, чем возвращать null. - person paparazzo; 03.09.2013
comment
@Blam нет, использовать dbnull не эффективнее, чем null. И да, некоторые соединения и т. д. оставляют данные без данных - ноль: но это не диктует нуль против dbnull - person Marc Gravell; 03.09.2013
comment
Нет смысла утверждать, что DBNull дублирует null, потому что null — это зло и недостаток дизайна. Конечно, принуждение к использованию object также является недостатком дизайна, но неверно говорить, что только object может содержать DBNull или другое значение — data-types-in-c.html" rel="nofollow noreferrer">тип суммы поможет. - person Doval; 22.01.2014
comment
Можно избежать двух ваших болевых точек: 1: необходимости работать с object и 2: нарушения объединения нулей в обмен на использование пространства имен System.Data.SqlTypes. Это не идеально (я бы предпочел использовать встроенные типы), но это работает. Например, int? example = null;SqlInt32 nocast = example ?? SqlInt32.Null; С точки зрения написания кода это не очень большая победа, но, по крайней мере, это легко читать. - person Brian; 06.05.2014
comment
@ Брайан, да, но проблема в том, чтобы исправить их обоих одним и тем же кодом. Любое из этих исправлений является взаимоисключающим с другим. - person Marc Gravell; 06.05.2014
comment
@ Брайан, а, я неправильно понял, что ты сказал. Проблема тогда заключается в том, что теперь вы привязываетесь к SqlClient, чего я настоятельно не рекомендую в общем случае. Существует множество веских причин для максимально возможного использования «голых» типов ADO.NET (а не типов, специфичных для провайдера). - person Marc Gravell; 06.05.2014

DbNull представляет собой коробку без содержимого; null указывает на отсутствие поля.

person Rikalous    schedule 20.12.2010
comment
Действительно? Хотите уточнить это? Я не понимаю. Тем более, что переменная (коробка) не исчезает, когда вы присваиваете ей null. - person Vilx-; 20.12.2010
comment
Если вы считаете, что переменная является адресом ящика, то, когда вы присваиваете значение null переменной, вы сообщаете переменной, что ящик больше не существует. То есть адрес не является «посещаемым». - person Rikalous; 20.12.2010
comment
Я согласен с тем, что документация совершенно неверна в том, что столбец не существует. - person Rikalous; 20.12.2010
comment
В той мере, в какой документация неверна, я подозреваю, что она была написана плохо, а не ошибочно. - person phoog; 10.01.2012
comment
CREATE PROC [Echo] @s varchar(max) = 'hello' AS SELECT @s [Echo]. SqlCommand cmd = новый SqlCommand(Echo); cmd.Parameters.AddWithValue(@s, ноль); Выполните команду и посмотрите на результат (будет использоваться значение параметра по умолчанию). Теперь измените значение параметра на DBNull.Value — процесс будет отображать предоставленное значение NULL. Существует семантическая разница между DBNull и null. Того же можно добиться, изменив параметры, но здесь одну и ту же команду можно использовать много раз, меняя только значения параметров - и это значительно быстрее. - person The Dag; 02.05.2013
comment
@TheDag, я не думаю, что эта функциональность стоит хлопот с проверкой и преобразованием как null, так и dbnull при использовании объектов, допускающих значение null. - person drigoangelo; 14.11.2013

Вы используете DBNull для отсутствующих данных. Null в языке .NET означает отсутствие указателя на объект/переменную.

Отсутствующие данные DBNull: http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx

Влияние отсутствия данных на статистику:

http://en.wikipedia.org/wiki/Missing_values

person jvdbogae    schedule 20.12.2010
comment
Что насчет Nullable<int> тогда? Это тип значения, без указателей. Может тогда это ошибка? - person Vilx-; 20.12.2010
comment
А также — что еще такое отсутствие указателя на объект, как не отсутствующие данные? - person Vilx-; 20.12.2010
comment
@Vilx, типов с нулевым значением не существовало в .NET 1.0/1.1, поэтому был необходим другой способ представления нулевых значений. - person Thomas Levesque; 20.12.2010
comment
@Thomas Levesque - я бы сказал, что ваш комментарий достоин быть ответом. Хотя это по-прежнему не объясняет, почему простой нуль нельзя было использовать так же хорошо. Чтобы создать переменную, которая может содержать как тип значения, так и DBNull, вам все равно придется сделать ее System.Object. - person Vilx-; 20.12.2010
comment
@ Томас, эта логика не работает; для хранения значения или DBNull нам нужно использовать object - это остается в случае 2.0+; object может отлично хранить null, так что даже при использовании object DBNull.Value по-прежнему является избыточным. - person Marc Gravell; 09.03.2012

Между CLR null и DBNull есть некоторые различия. Во-первых, null в реляционных базах данных имеет другую семантику «равно»: null не равно null. CLR null равен нулю.

Но я подозреваю, что основная причина связана с тем, как значения параметров по умолчанию работают на сервере SQL и с реализацией поставщика.

Чтобы увидеть разницу, создайте процедуру с параметром, имеющим значение по умолчанию:

CREATE PROC [Echo] @s varchar(MAX) = 'hello'
AS
    SELECT @s [Echo]

Хорошо структурированный код DAL должен отделять создание команд от их использования (чтобы можно было многократно использовать одну и ту же команду, например, многократно эффективно вызывать хранимую процедуру). Напишите метод, который возвращает SqlCommand, представляющий описанную выше процедуру:

SqlCommand GetEchoProc()
{
    var cmd = new SqlCommand("Echo");
    cmd.Parameters.Add("@s", SqlDbType.VarChar);
    return cmd;
}

Если теперь вы вызовете команду, не задав параметр @s, или установите для него значение (CLR) null, будет использоваться значение по умолчанию «hello». Если, с другой стороны, вы установите значение параметра в DBNull.Value, оно будет использовать его и выводить DbNull.Value.

Поскольку есть два разных результата, использующих в качестве значения параметра значение CLR null или значение null базы данных, вы не можете представить оба случая только с одним из них. Если бы CLR null был единственным, он должен был бы работать так, как сегодня работает DBNull.Value. Один из способов указать провайдеру «Я хочу использовать значение по умолчанию» может состоять в том, чтобы вообще не объявлять параметр (параметр со значением по умолчанию, конечно, имеет смысл описывать как «необязательный параметр»), но в сценарий, в котором объект команды кэшируется и используется повторно, приводит к удалению и повторному добавлению параметра.

Я не уверен, считаю ли я DBNull хорошей идеей или нет, но многие люди не знают о вещах, которые я здесь упомянул, поэтому я решил, что об этом стоит упомянуть.

person The Dag    schedule 02.05.2013
comment
Теперь я также кое-что узнал: DBNull на самом деле не имеет равной семантики нулевых значений базы данных. Однако второй пункт остается в силе - DBNull или null действительно работают по-разному в качестве значений параметров. - person The Dag; 02.05.2013
comment
Я думаю, что распространено мнение, что несоответствие DBNull и null изначально существовало, потому что .NET и SQL Server изначально создавались отдельными командами. Сомнительно, существуют ли два нуля сейчас как наследие этой отдельной команды или как нечто, что на самом деле приносит больше пользы, чем раздражает. - person 1c1cle; 18.11.2013

Чтобы ответить на ваш вопрос, вы должны подумать, почему DBNull вообще существует?

DBNull необходим в узком случае использования. В противном случае это не так. Большинству людей никогда не понадобится DBNull. Я никогда не позволяю их вводить в хранилища данных, которые я разрабатываю. У меня ВСЕГДА есть значение, поэтому мои данные никогда не бывают ‹null›, я всегда выбираю тип, осмысленный как «значение по умолчанию», и мне никогда не приходится делать эту абсурдную двойную проверку всего дважды в коде, один раз для объекта null и снова ибо это DBNull, прежде чем я приведу свой объект к моему фактическому типу данных (например, Int и т. д.).

DBNull необходим в одном случае, который вам может понадобиться... если вы используете некоторые функции статистики SQL (например, медиана, среднее)... они специально обрабатывают DBNull... посмотрите эти документы... некоторые функции не включают DBNull в общем подсчете статистики... например: (сумма 87/всего 127) против (сумма 87/всего 117)... разница в том, что 10 из этих значений столбца были DBNull... вы можете видеть, что это изменится результат статистики.

Мне не нужно проектировать свои базы данных с помощью DBNull. Если бы мне когда-нибудь понадобились статистические результаты, я бы явно изобрел или добавил столбец, такой как «UserDidProvideValue», для этого одного элемента, который требует какой-то специальной обработки, потому что он не существует (например, мое общее количество 117 будет суммой полей, отмеченных UserDidProvideValue=true) ... ха-ха, лол - в моей следующей жизни как правителя Вселенной, лол - DBNull никогда бы не позволили покинуть царство SQL... весь мир программирования теперь обязан проверять все дважды... когда у вас когда-нибудь было мобильное приложение, настольное приложение или веб-сайт, которым нужно было иметь нулевое целое число? - Никогда...

person user2014638    schedule 27.06.2020
comment
Оооо, собираешься получить значок Некроманта? :) Я вижу более одного хорошего варианта использования значения null в БД. На самом деле иногда мне хотелось бы определить более одного специального значения. - person Vilx-; 27.06.2020
comment
Вот один очень распространенный вариант использования: необязательные внешние ключи. Если есть значение (даже значение по умолчанию), вам нужна запись в удаленной таблице. Однако нулевые значения не требуют записи в удаленной таблице. Конечно, вы могли бы сказать - ОК, но затем создать эту запись по умолчанию в удаленной таблице с фиксированным идентификатором. Но тогда вам нужно жестко закодировать идентификаторы БД в коде вашего приложения, и вам также нужно не забыть пропустить эту запись, где бы вы ни перечисляли значения из этой удаленной таблицы. - person Vilx-; 27.06.2020
comment
Я вижу, как почти любое значение null можно удалить, разделив один столбец на два: один будет содержать нулевое значение (и, возможно, даже другие специальные значения, как я хотел выше), а другие фактические данные (которые используются только тогда, когда нулевое значение равно false) . Но будет ли это лучше? Я не уверен... мой первый инстинкт подсказывает, что в коде будет намного больше IFs и CASEs в SQL, так как теперь мне нужно смотреть на два столбца вместо одного. И мне потребуется множество CHECK ограничений для обеспечения целостности данных. - person Vilx-; 27.06.2020