Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Значение NULL в реляционной базе данных используется, если значение в столбце неизвестно или отсутствует. Значение NULL не является пустой строкой (для типов данных символа или даты и времени) или нулевого значения (для числовых типов данных). Спецификация ANSI SQL-92 указывает, что значение NULL должно быть одинаковым для всех типов данных, чтобы все значения NULL обрабатывались согласованно. Пространство имен System.Data.SqlTypes предоставляет нулевую семантику, реализуя интерфейс INullable. Каждый из типов данных в System.Data.SqlTypes имеет собственное IsNull
свойство и Null
значение, которое можно назначить экземпляру данного типа данных.
Замечание
Платформа .NET Framework версии 2.0 представила поддержку типов значений, допускающих значение NULL, что позволяет программистам расширить тип значения для представления всех значений базового типа. Типы значений CLR, допускающие значение NULL, представляют экземпляр структуры Nullable. Эта возможность особенно полезна, если типы значений упаковываются и распаковываются, обеспечивая улучшенную совместимость с типами объектов. nullable типы значений CLR не предназначены для хранения значений NULL базы данных, так как NULL ANSI SQL не ведет себя так же, как null
ссылка (или Nothing
в Visual Basic). Для работы со значениями null в базе данных ANSI SQL используйте System.Data.SqlTypes вместо Nullable. Дополнительные сведения о работе с CLR-значениями, допускающими значение NULL, в Visual Basic см. в разделе Типы значений, допускающие значение NULL, а для C# см. Типы значений, допускающие значение NULL.
Нули и Three-Valued логика
Разрешение значений NULL в определениях столбцов вводит в приложение трехзначную логику. Сравнение может оценить одно из трех условий:
Верно
Неправда
Неизвестно
Поскольку значение NULL считается неизвестным, два значения NULL по сравнению с другими не считаются равными. В выражениях с использованием арифметических операторов, если любой из операндов имеет значение NULL, результат также имеет значение NULL.
Пустые значения и SqlBoolean
Сравнение любого System.Data.SqlTypes вернет SqlBoolean. Функция IsNull
для каждого SqlType
возвращает значение SqlBoolean и может использоваться для проверки значений NULL. В следующих таблицах истины показано, как операторы AND, OR и NOT работают в присутствии значения NULL. (T=true, F=false и U=неизвестно, или нулевое.)
Общие сведения о параметре ANSI_NULLS
System.Data.SqlTypes предоставляет ту же семантику, что и при установке параметра ANSI_NULLS в SQL Server. Все арифметические операторы (+, -, *, /, %), побитовые операторы (~, &, |) и большинство функций возвращают значение NULL, если любой из операндов или аргументов имеет значение NULL, за исключением свойства IsNull
.
Стандарт ANSI SQL-92 не поддерживает columnName = NULL в предложении WHERE. В SQL Server параметр ANSI_NULLS управляет значением NULL по умолчанию в базе данных и оценке сравнений со значениями NULL. Если ANSI_NULLS включен (по умолчанию), оператор IS NULL должен использоваться в выражениях при тестировании значений NULL. Например, следующее сравнение всегда приводит к результату "неизвестно", когда ANSI_NULLS включен:
colname > NULL
Сравнение с переменной, содержащей значение NULL, также дает неизвестное значение:
colname > @MyVariable
Используйте предикат IS NULL или IS NOT NULL, чтобы проверить значение NULL. Это может добавить сложность в предложение WHERE. Например, столбец TerritoryID в таблице AdventureWorks Customer допускает значения NULL. Если оператор SELECT должен проверять значения NULL, а также другие значения, он должен включать предикат IS NULL.
SELECT CustomerID, AccountNumber, TerritoryID
FROM AdventureWorks.Sales.Customer
WHERE TerritoryID IN (1, 2, 3)
OR TerritoryID IS NULL
Если отключить ANSI_NULLS в SQL Server, можно создать выражения, использующие оператор равенства для сравнения с null. Однако не удается запретить другим подключениям задавать параметры NULL для этого подключения. Использование IS NULL для проверки значений NULL всегда работает независимо от ANSI_NULLS параметров подключения.
Если отключить ANSI_NULLS, это не поддерживается в DataSet
, который всегда следует стандарту ANSI SQL-92 для обработки значений NULL в System.Data.SqlTypes.
Назначение значений NULL
Значения NULL являются особыми, а их семантика хранения и назначения отличаются в разных системах типов и системах хранения. A Dataset
предназначен для использования с различными типами и системами хранения.
В этом разделе описывается семантика присвоения нулевых значений элементам DataColumn в различных системах типов DataRow.
DBNull.Value
Это назначение допустимо для DataColumn
любого типа. Если тип реализует INullable
, DBNull.Value
приводится в строго типизированное значение null.
SqlType.Null
Все System.Data.SqlTypes типы данных реализуют INullable
. Если строго типизированное значение NULL можно преобразовать в тип данных столбца с помощью неявных операторов приведения, присвоение должно выполниться. В противном случае создается недопустимое исключение приведения.
null
Если значение "null" является законным для данного DataColumn
типа данных, оно приводится к соответствующему DbNull.Value
или Null
, связанному с типом INullable
(SqlType.Null
)
derivedUdt.Null
Для столбцов определяемых пользователем типов, NULL-значения всегда хранятся в зависимости от типа, связанного с ним DataColumn
. Рассмотрим случай пользовательского типа (UDT), связанного с DataColumn
, который не реализует INullable
, в то время как его подкласс это делает. В этом случае, если присваивается строго типизированное значение NULL, связанное с производным классом, оно хранится как нетипизированное DbNull.Value
, так как хранилище NULL всегда соответствует типу данных DataColumn.
Замечание
В настоящее время структура Nullable<T>
или Nullable не поддерживается в DataSet
.
Значение по умолчанию для любого System.Data.SqlTypes экземпляра равно NULL.
NULL в System.Data.SqlTypes являются специфичными для типа и не могут быть представлены одним значением, таким как DbNull
. Используйте свойство IsNull
для проверки нулевых значений.
Нулевые значения можно присвоить DataColumn, как показано в следующем примере кода. Можно напрямую назначать значения SqlTypes
NULL переменным без активации исключения.
Пример
В следующем примере кода создается DataTable, в котором имеются два столбца, определенные как SqlInt32 и SqlString. Код добавляет одну строку известных значений, одну строку значений NULL, а затем выполняет итерацию, DataTableприсваивая значения переменным и отображая выходные данные в окне консоли.
static void WorkWithSqlNulls()
{
DataTable table = new();
// Specify the SqlType for each column.
DataColumn idColumn =
table.Columns.Add("ID", typeof(SqlInt32));
DataColumn descColumn =
table.Columns.Add("Description", typeof(SqlString));
// Add some data.
DataRow nRow = table.NewRow();
nRow["ID"] = 123;
nRow["Description"] = "Side Mirror";
table.Rows.Add(nRow);
// Add null values.
nRow = table.NewRow();
nRow["ID"] = SqlInt32.Null;
nRow["Description"] = SqlString.Null;
table.Rows.Add(nRow);
// Initialize variables to use when
// extracting the data.
SqlBoolean isColumnNull = false;
SqlInt32 idValue = SqlInt32.Zero;
SqlString descriptionValue = SqlString.Null;
// Iterate through the DataTable and display the values.
foreach (DataRow row in table.Rows)
{
// Assign values to variables. Note that you
// do not have to test for null values.
idValue = (SqlInt32)row["ID"];
descriptionValue = (SqlString)row["Description"];
// Test for null value in ID column.
isColumnNull = idValue.IsNull;
// Display variable values in console window.
Console.Write("isColumnNull={0}, ID={1}, Description={2}",
isColumnNull, idValue, descriptionValue);
Console.WriteLine();
}
Private Sub WorkWithSqlNulls()
Dim table As New DataTable()
' Specify the SqlType for each column.
Dim idColumn As DataColumn = _
table.Columns.Add("ID", GetType(SqlInt32))
Dim descColumn As DataColumn = _
table.Columns.Add("Description", GetType(SqlString))
' Add some data.
Dim row As DataRow = table.NewRow()
row("ID") = 123
row("Description") = "Side Mirror"
table.Rows.Add(row)
' Add null values.
row = table.NewRow()
row("ID") = SqlInt32.Null
row("Description") = SqlString.Null
table.Rows.Add(row)
' Initialize variables to use when
' extracting the data.
Dim isColumnNull As SqlBoolean = False
Dim idValue As SqlInt32 = SqlInt32.Zero
Dim descriptionValue As SqlString = SqlString.Null
' Iterate through the DataTable and display the values.
For Each row In table.Rows
' Assign values to variables. Note that you
' do not have to test for null values.
idValue = CType(row("ID"), SqlInt32)
descriptionValue = CType(row("Description"), SqlString)
' Test for null value with ID column
isColumnNull = idValue.IsNull
' Display variable values in console window.
Console.Write("isColumnNull={0}, ID={1}, Description={2}", _
isColumnNull, idValue, descriptionValue)
Console.WriteLine()
Next row
End Sub
В этом примере отображаются следующие результаты:
isColumnNull=False, ID=123, Description=Side Mirror
isColumnNull=True, ID=Null, Description=Null
Назначение нескольких столбцов или строк
DataTable.Add
, DataTable.LoadDataRow
или другие API, которые принимают значение ItemArray, которое сопоставляется со строкой, сопоставляют 'null' со значением по умолчанию DataColumn. Если объект в массиве содержит DbNull.Value
или его строго типизированный аналог, применяются те же правила, что и описано выше.
Кроме того, для экземпляра назначений DataRow.["columnName"]
NULL применяются следующие правила:
Значение по умолчанию применяется ко всем, кроме строго типизированных столбцов NULL, где используется соответствующее строго типизированное значение NULL.
Значения NULL никогда не записываются во время сериализации в XML-файлы (как в xsi:nil).
Все значения, отличные от NULL, включая значения по умолчанию, всегда записываются при сериализации в XML. Это в отличие от семантики XSD/XML, где значение NULL (xsi:nil) явно, и значение по умолчанию неявно (если оно отсутствует в XML, проверяющий средство синтаксического анализа может получить его из связанной схемы XSD). Верно обратное для
DataTable
: значение NULL неявно, а значение по умолчанию явно.Все отсутствующие значения столбцов для строк, считываемых из входных данных XML, назначаются NULL. Строкам, созданным с помощью NewRow или с помощью аналогичных методов, присваивается значение по умолчанию столбца данных.
Метод IsNull возвращает
true
как дляDbNull.Value
, так и дляINullable.Null
.
Сравнение значений NULL с типами SQLTypes и CLR
При сравнении значений NULL важно понимать разницу между тем, как метод Equals
оценивает значения NULL в System.Data.SqlTypes и тем, как он работает с типами CLR.
System.Data.SqlTypes
Equals
Все методы используют семантику базы данных для оценки значений NULL: если одно или оба значения равно NULL, сравнение дает значение NULL. С другой стороны, использование метода CLR Equals
в двух System.Data.SqlTypes случаях будет иметь значение true, если оба значения имеют значение NULL. Это отражает разницу между использованием метода экземпляра, такого как метод CLR String.Equals
, и использованием статического или общего метода SqlString.Equals
.
В следующем примере показано различие в результатах между SqlString.Equals
методом и String.Equals
методом при передаче пары значений NULL, а затем пары пустых строк.
static void CompareNulls()
{
// Create two new null strings.
SqlString a = new();
SqlString b = new();
// Compare nulls using static/shared SqlString.Equals.
Console.WriteLine("SqlString.Equals shared/static method:");
Console.WriteLine($" Two nulls={SqlStringEquals(a, b)}");
// Compare nulls using instance method String.Equals.
Console.WriteLine();
Console.WriteLine("String.Equals instance method:");
Console.WriteLine($" Two nulls={StringEquals(a, b)}");
// Make them empty strings.
a = "";
b = "";
// When comparing two empty strings (""), both the shared/static and
// the instance Equals methods evaluate to true.
Console.WriteLine();
Console.WriteLine("SqlString.Equals shared/static method:");
Console.WriteLine($" Two empty strings={SqlStringEquals(a, b)}");
Console.WriteLine();
Console.WriteLine("String.Equals instance method:");
Console.WriteLine($" Two empty strings={StringEquals(a, b)}");
}
static string SqlStringEquals(SqlString string1, SqlString string2)
{
// SqlString.Equals uses database semantics for evaluating nulls.
var returnValue = SqlString.Equals(string1, string2).ToString();
return returnValue;
}
static string StringEquals(SqlString string1, SqlString string2)
{
// String.Equals uses CLR type semantics for evaluating nulls.
var returnValue = string1.Equals(string2).ToString();
return returnValue;
}
}
Private Sub CompareNulls()
' Create two new null strings.
Dim a As New SqlString
Dim b As New SqlString
' Compare nulls using static/shared SqlString.Equals.
Console.WriteLine("SqlString.Equals shared/static method:")
Console.WriteLine(" Two nulls={0}", SqlStringEquals(a, b))
' Compare nulls using instance method String.Equals.
Console.WriteLine()
Console.WriteLine("String.Equals instance method:")
Console.WriteLine(" Two nulls={0}", StringEquals(a, b))
' Make them empty strings.
a = ""
b = ""
' When comparing two empty strings (""), both the shared/static and
' the instance Equals methods evaluate to true.
Console.WriteLine()
Console.WriteLine("SqlString.Equals shared/static method:")
Console.WriteLine(" Two empty strings={0}", SqlStringEquals(a, b))
Console.WriteLine()
Console.WriteLine("String.Equals instance method:")
Console.WriteLine(" Two empty strings={0}", StringEquals(a, b))
End Sub
Private Function SqlStringEquals(ByVal string1 As SqlString, _
ByVal string2 As SqlString) As String
' SqlString.Equals uses database semantics for evaluating nulls.
Dim returnValue As String = SqlString.Equals(string1, string2).ToString()
Return returnValue
End Function
Private Function StringEquals(ByVal string1 As SqlString, _
ByVal string2 As SqlString) As String
' String.Equals uses CLR type semantics for evaluating nulls.
Dim returnValue As String = string1.Equals(string2).ToString()
Return returnValue
End Function
Код создает следующие выходные данные:
SqlString.Equals shared/static method:
Two nulls=Null
String.Equals instance method:
Two nulls=True
SqlString.Equals shared/static method:
Two empty strings=True
String.Equals instance method:
Two empty strings=True