SELECT CustomerID, AccountNumber, TerritoryID
FROM AdventureWorks.Sales.Customer
WHERE TerritoryID IN (1, 2, 3)
OR TerritoryID IS NULL
如果在 SQL Server 将 ANSI_NULLS 设置为关闭,则可以创建使用相等运算符与 null 进行比较的表达式。 但是,不能阻止不同的连接为该连接设置 null 选项。 使用 IS NULL 测试 null 值始终有效,而不考虑连接的 ANSI_NULLS 设置。
不支持在 DataSet
中将 ANSI_NULLS 设置为关闭,这始终遵循 ANSI SQL-92 标准来处理 System.Data.SqlTypes 中的 null 值。
赋予 Null 值
null 值为特殊值,其存储和赋值语义在不同类型系统和存储系统之间是不同的。 Dataset
旨在与不同的类型和存储系统一起使用。
本部分介绍 null 语义,该语义用于将 null 值分配给不同类型系统中 DataColumn 的 DataRow。
DBNull.Value
该赋值对于任何类型的 DataColumn
都有效。 如果类型实现 INullable
,则会将 DBNull.Value
强制转换为相应的强类型 Null 值。
SqlType.Null
所有 System.Data.SqlTypes 数据类型都实现 INullable
。 如果可使用隐式强制转换运算符将强类型的 null 值转换为列的数据类型,则应执行赋值。 否则,将引发无效强制转换异常。
如果“null”是给定 DataColumn
数据类型的合法值,则会将其强制转换为与 DbNull.Value
类型 (Null
) 关联的相应 INullable
或 SqlType.Null
derivedUdt.Null
对于 UDT 列,将始终基于与 DataColumn
关联的类型存储 null 值。 请考虑与 DataColumn
关联的 UDT 的情况,它不实现 INullable
,但其子类会实现。 在这种情况下,如果分配了与派生类关联的强类型 null 值,则会将其存储为非类型化的 DbNull.Value
,因为 null 存储始终与 DataColumn 的数据类型一致。
Nullable<T>
当前不支持 Nullable 或 DataSet
结构。
任何 System.Data.SqlTypes 实例的默认值为 null。
System.Data.SqlTypes 中的 null 值为特定类型,不能由单个值表示,如 DbNull
。 使用 IsNull
属性检查 null 值。
null 值可以分配给 DataColumn,如下面的代码示例中所示。 可以直接将 null 值分配给 SqlTypes
变量,而不会触发异常。
下面的代码示例创建一个 DataTable,其中两列定义为 SqlInt32 和 SqlString。 该代码将添加一行已知值、一行 null 值,然后循环访问 DataTable,进而将值分配给变量并在控制台窗口中显示输出。
static private void WorkWithSqlNulls()
DataTable table = new DataTable();
// 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
或接受映射到行的 ItemArray 的其他 API,请将“null”映射到 DataColumn 的默认值。 如果数组中的对象包含 DbNull.Value
或其强类型对应项,则将应用上述规则。
此外,以下规则适用于 DataRow.["columnName"]
null 赋值的实例:
所有列的默认值均为 DbNull.Value
,但强类型 null 列除外,此列的默认值是相应的强类型 null 值。
在序列化为 XML 文件时,不会写出 null 值(如在“xsi:nil”中)。
在序列化为 XML 时,始终写出所有非 null 值(包括默认值)。 这不同于 XSD/XML 语义,其中 null 值 (xsi:nil) 是显式的,而默认值是隐式的(如果在 XML 中不存在,验证分析器可以从关联的 XSD 架构中获取它)。 DataTable
则是相反:null 值是隐式的,而默认值是显式的。
从 XML 输入读取的行的所有缺少列值都将分配为 NULL。 将向使用 NewRow 或类似方法创建的行分配 DataColumn 的默认值。
IsNull 方法为 true
和 DbNull.Value
返回 INullable.Null
。
将空值与 SqlTypes 和 CLR 类型进行比较
比较 null 值时,务必要了解 Equals
方法计算 System.Data.SqlTypes 中 null 值的方式与它在 CLR 类型中的工作方式相比之间的差异。 所有 System.Data.SqlTypesEquals
方法都使用数据库语义计算 null 值:如果两个值中的一个或两个都为 null,则比较结果为 null。 另一方面,如果两个 Equals
都为 null,则对两者使用 CLR System.Data.SqlTypes 方法将生成 true。 这反映了使用实例方法(如 CLR String.Equals
方法)和使用静态/共享方法 (SqlString.Equals
) 的差异。
下面的示例演示了 SqlString.Equals
方法与 String.Equals
方法在分别传递一对 null 值和一对空字符串时的结果差异。
private static void CompareNulls()
// Create two new null strings.
SqlString a = new SqlString();
SqlString b = 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));
private static string SqlStringEquals(SqlString string1, SqlString string2)
// SqlString.Equals uses database semantics for evaluating nulls.
string returnValue = SqlString.Equals(string1, string2).ToString();
return returnValue;
private static string StringEquals(SqlString string1, SqlString string2)
// String.Equals uses CLR type semantics for evaluating nulls.
string 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
SQL Server 数据类型和 ADO.NET
ADO.NET 概述