null 値の処理Handling Null Values

列の値が不明または欠落している場合は、リレーショナル データベースの NULL 値が使用されます。A null value in a relational database is used when the value in a column is unknown or missing. NULL は空文字列 (文字または日付時刻データ型) でもゼロ値 (数値データ型) でもありません。A null is neither an empty string (for character or datetime data types) nor a zero value (for numeric data types). ANSI SQL-92 の規格では、すべてのデータ型について NULL は同一でなければならないと規定されているため、すべての NULL が一貫して処理されます。The ANSI SQL-92 specification states that a null must be the same for all data types, so that all nulls are handled consistently. System.Data.SqlTypes 名前空間では、INullable インターフェイスを実装することで NULL セマンティクスが提供されます。The System.Data.SqlTypes namespace provides null semantics by implementing the INullable interface. System.Data.SqlTypes 内の各データ型には、それぞれ独自に IsNull プロパティと Null 値があり、データ型のインスタンスに割り当てることができます。Each of the data types in System.Data.SqlTypes has its own IsNull property and a Null value that can be assigned to an instance of that data type.

注意

.NET Framework version 2.0 では、NULL 許容型がサポートされました。この型を使用することで、値型を拡張して基になる型のすべての値を表すことができます。The .NET Framework version 2.0 introduced support for nullable types, which allow programmers to extend a value type to represent all values of the underlying type. これらの CLR NULL 許容型は、Nullable 構造体のインスタンスを表します。These CLR nullable types represent an instance of the Nullable structure. この機能は、値の型がボックスまたはアンボックスされるときに特に有効であり、オブジェクト型との互換性が強化されます。This capability is especially useful when value types are boxed and unboxed, providing enhanced compatibility with object types. ANSI SQL の NULL は null 参照 (Visual Basic では Nothing) と動作が異なるため、CLR NULL 許容型は NULL のデータベースへの格納を意図したものではありません。CLR nullable types are not intended for storage of database nulls because an ANSI SQL null does not behave the same way as a null reference (or Nothing in Visual Basic). データベースの ANSI SQL NULL 値を操作するには、System.Data.SqlTypes ではなく Nullable NULL を使用します。For working with database ANSI SQL null values, use System.Data.SqlTypes nulls rather than Nullable. での CLR null 許容型の使用の詳細についてはVisual Basic 「null 許容値型」および「」 C# を参照してください。For more information on working with CLR nullable types in Visual Basic see Nullable Value Types, and for C# see Nullable value types.

NULL および 3 つの値を持つロジックNulls and Three-Valued Logic

列定義に NULL 値を許可することで、3 つの値を持つロジックをアプリケーションに定義できます。Allowing null values in column definitions introduces three-valued logic into your application. 比較によって、次の 3 つの条件のうちの 1 つを評価できます。A comparison can evaluate to one of three conditions:

  • TrueTrue

  • FalseFalse

  • 不明Unknown

NULL は不明であるとされるため、2 つの NULL 値を相互に比較した場合、同等であるとは見なされません。Because null is considered to be unknown, two null values compared to each other are not considered to be equal. 算術演算子を使用する式では、オペランドのいずれかが NULL である場合は結果も NULL になります。In expressions using arithmetic operators, if any of the operands is null, the result is null as well.

NULL および SqlBooleanNulls and SqlBoolean

System.Data.SqlTypes 間の比較により、SqlBoolean が返されます。Comparison between any System.Data.SqlTypes will return a SqlBoolean. IsNullSqlType 関数により、SqlBoolean が返され、NULL 値の確認に使用できます。The IsNull function for each SqlType returns a SqlBoolean and can be used to check for null values. 次の truth テーブルは、NULL 値がある場合の AND、OR、および NOT 演算子の機能を示しますThe following truth tables show how the AND, OR, and NOT operators function in the presence of a null value. (T=true、F=false、U=不明または NULL)。(T=true, F=false, and U=unknown, or null.)

真理テーブルTruth Table

ANSI_NULLS オプションについてUnderstanding the ANSI_NULLS Option

System.Data.SqlTypes では、ANSI_NULLS オプションが SQL Server で設定された場合と同じセマンティクスになります。System.Data.SqlTypes provides the same semantics as when the ANSI_NULLS option is set on in SQL Server. すべての算術演算子 (+、-、*、/、%)、ビットごとの演算子 (~、&、|)、およびほとんどの関数は、プロパティ IsNullを除き、オペランドまたは引数のいずれかが null の場合は null を返します。All arithmetic operators (+, -, *, /, %), bitwise operators (~, &, |), and most functions return null if any of the operands or arguments is null, except for the property IsNull.

ANSI SQL-92 標準では、WHERE 句でcolumnName = NULL はサポートされていません。The ANSI SQL-92 standard does not support columnName = NULL in a WHERE clause. SQL Server では、ANSI_NULLS オプションによって、データベース内の既定の NULL 値と、NULL 値に対する比較の評価の両方が制御されます。In SQL Server, the ANSI_NULLS option controls both default nullability in the database and evaluation of comparisons against null values. ANSI_NULLS がオン (既定) である場合、IS NULL 演算子を NULL 値のテストを行う式で使用する必要があります。If ANSI_NULLS is turned on (the default), the IS NULL operator must be used in expressions when testing for null values. たとえば次の比較では、ANSI_NULLS がオンである場合、常に不明となります。For example, the following comparison always yields unknown when ANSI_NULLS is on:

colname > NULL  

NULL 値を含む変数との比較でも不明となります。Comparison to a variable containing a null value also yields unknown:

colname > @MyVariable  

NULL 値をテストするには、IS NULL または IS NOT NULL 述語を使用します。Use the IS NULL or IS NOT NULL predicate to test for a null value. これにより WHERE 句が複雑になる場合があります。This can add complexity to the WHERE clause. たとえば、AdventureWorks Customer テーブル内の TerritoryID 列では、NULL 値が許可されています。For example, the TerritoryID column in the AdventureWorks Customer table allows null values. SELECT ステートメントによってその他の値と合わせて NULL 値もテストされる場合は、IS NULL 述語を含める必要があります。If a SELECT statement is to test for null values in addition to others, it must include an IS NULL predicate:

SELECT CustomerID, AccountNumber, TerritoryID  
FROM AdventureWorks.Sales.Customer  
WHERE TerritoryID IN (1, 2, 3)  
   OR TerritoryID IS NULL  

SQL Server で ANSI_NULLS をオフに設定すると、等値演算子を使用する式を作成し、NULL 値と比較できます。If you set ANSI_NULLS off in SQL Server, you can create expressions that use the equality operator to compare to null. ただし、別の接続からその接続に対して NULL オプションを設定することを防ぐことはできません。However, you can't prevent different connections from setting null options for that connection. IS NULL を使用した NULL 値のテストは、接続の ANSI_NULLS 設定にかかわらず、常に動作します。Using IS NULL to test for null values always works, regardless of the ANSI_NULLS settings for a connection.

DataSet では、ANSI_NULLS をオフに設定することはできません。System.Data.SqlTypes における NULL 値の処理については、常に ANSI SQL-92 標準に準拠します。Setting ANSI_NULLS off is not supported in a DataSet, which always follows the ANSI SQL-92 standard for handling null values in System.Data.SqlTypes.

NULL 値の割り当てAssigning Null Values

NULL 値は特殊であり、ストレージおよび割り当てのセマンティクスは、システムおよびストレージ システムの種類によって異なります。Null values are special, and their storage and assignment semantics differ across different type systems and storage systems. Dataset は、異なる種類のシステムおよびストレージ システムで使用できるように設計されています。A Dataset is designed to be used with different type and storage systems.

このセクションでは、異なる種類のシステム上にある DataColumnDataRow に NULL 値を割り当てるための NULL セマンティクスについて説明します。This section describes the null semantics for assigning null values to a DataColumn in a DataRow across the different type systems.

DBNull.Value
この割り当ては、任意の型の DataColumn で有効です。This assignment is valid for a DataColumn of any type. その型が INullable を実装している場合は、DBNull.Value が厳密に型指定された適切な NULL 値に強制的に変換されます。If the type implements INullable, DBNull.Value is coerced into the appropriate strongly typed Null value.

SqlType.Null
すべての System.Data.SqlTypes データ型で INullable を実装します。All System.Data.SqlTypes data types implement INullable. 暗黙的なキャスト演算子を使用して、厳密に型指定された NULL 値を列のデータ型に変換できる場合は、割り当てが行われます。If the strongly typed null value can be converted into the column's data type using implicit cast operators, the assignment should go through. 変換できない場合は、無効なキャスト例外がスローされます。Otherwise an invalid cast exception is thrown.

null
特定の DataColumn データ型について 'null' が有効であった場合、DbNull.Value 型 (Null) に関連付けられている、適切な INullable または SqlType.Null に強制的に変換されます。If 'null' is a legal value for the given DataColumn data type, it is coerced into the appropriate DbNull.Value or Null associated with the INullable type (SqlType.Null)

derivedUdt.Null
UDT 列の場合、NULL 値は常に DataColumn に関連付けられている型に基づいて格納されます。For UDT columns, nulls are always stored based on the type associated with the DataColumn. DataColumn に関連付けられている UDT が INullable を実装せず、サブクラスで実装される場合を考えます。Consider the case of a UDT associated with a DataColumn that does not implement INullable while its sub-class does. この場合、派生クラスに関連付けられた厳密に型指定された NULL 値が割り当てられていれば、NULL ストレージが常に DataColumn のデータ型と一致するため、型指定されていない DbNull.Value として格納されます。In this case, if a strongly typed null value associated with the derived class is assigned, it is stored as an untyped DbNull.Value, because null storage is always consistent with the DataColumn's data type.

注意

Nullable<T> または Nullable 構造体は、現在 DataSet ではサポートされていません。The Nullable<T> or Nullable structure is not currently supported in the DataSet.

複数列 (行) の割り当てMultiple Column (Row) Assignment

DataTable.Add を行にマップできる、DataTable.LoadDataRowItemArray などの API については、DataColumn の既定値に 'null' をマップします。DataTable.Add, DataTable.LoadDataRow, or other APIs that accept an ItemArray that gets mapped to a row, map 'null' to the DataColumn's default value. 配列内のオブジェクトに DbNull.Value またはその厳密に型指定された値が含まれる場合は、上記と同じ規則が適用されます。If an object in the array contains DbNull.Value or its strongly typed counterpart, the same rules as described above are applied.

さらに、DataRow.["columnName"] の NULL 値割り当てのインスタンスには、次の規則が適用されます。In addition, the following rules apply for an instance of DataRow.["columnName"] null assignments:

  1. 既定の既定値は、厳密に型指定された null 列を除く、厳密に型指定された適切な null 値であるすべてのに対して DbNull.Value です。The default default value is DbNull.Value for all except the strongly typed null columns where it is the appropriate strongly typed null value.

  2. XML ファイルへのシリアル化中に NULL 値が書き出されることはありません ("xsi:nil" と同じ)。Null values are never written out during serialization to XML files (as in "xsi:nil").

  3. 既定値を含む NULL 以外のすべての値は、常に XML へのシリアル化中に書き出されます。All non-null values, including defaults, are always written out while serializing to XML. これは、NULL 値 (xsi:nil) が明示的で既定値が暗黙的である、XSD/XML セマンティクスとは異なります (XML にない場合は、検証パーサーが関連付けられた XSD スキーマから取得します)。This is unlike XSD/XML semantics where a null value (xsi:nil) is explicit and the default value is implicit (if not present in XML, a validating parser can get it from an associated XSD schema). 逆に DataTable では、NULL 値が暗黙的で、既定値が明示的になります。The opposite is true for a DataTable: a null value is implicit and the default value is explicit.

  4. XML 入力から読み取られた各行の欠落している列値にはすべて、NULL が割り当てられます。All missing column values for rows read from XML input are assigned NULL. NewRow または類似のメソッドを使用して作成された行には、DataColumn の既定値が割り当てられます。Rows created using NewRow or similar methods are assigned the DataColumn's default value.

  5. IsNull メソッドは、trueDbNull.Value のどちらに対しても INullable.Null を返します。The IsNull method returns true for both DbNull.Value and INullable.Null.

NULL 値の割り当てAssigning Null Values

任意の System.Data.SqlTypes インスタンスの既定値は NULL です。The default value for any System.Data.SqlTypes instance is null.

System.Data.SqlTypes の NULL 値は型固有であり、DbNull などの 1 つの値で表すことはできません。Nulls in System.Data.SqlTypes are type-specific and cannot be represented by a single value, such as DbNull. NULL 値の確認には、IsNull プロパティを使用します。Use the IsNull property to check for nulls.

NULL 値は、次のコード サンプルに示すように DataColumn に割り当てることができます。Null values can be assigned to a DataColumn as shown in the following code example. NULL 値は、例外をトリガーすることなく SqlTypes 変数に直接割り当てることができます。You can directly assign null values to SqlTypes variables without triggering an exception.

Example

次のコード サンプルでは、DataTable および SqlInt32 として定義される 2 つの列を持つ SqlString が作成されます。The following code example creates a DataTable with two columns defined as SqlInt32 and SqlString. このコードでは既知の値の行が 1 行、NULL 値の行が 1 行追加され、DataTable を通じて反復処理されます。これにより値が変数に割り当てられ、コンソール ウィンドウに出力が表示されます。The code adds one row of known values, one row of null values and then iterates through the DataTable, assigning the values to variables and displaying the output in the console window.

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

この例を実行すると、次の結果が表示されます。This example displays the following results:

isColumnNull=False, ID=123, Description=Side Mirror  
isColumnNull=True, ID=Null, Description=Null  

NULL 値と SqlTypes および CLR 型との比較Comparing Null Values with SqlTypes and CLR Types

NULL 値を比較する場合は、Equals メソッドによって System.Data.SqlTypes で NULL 値を評価する方法と、CLR 型を使用する方法との違いを理解することが重要です。When comparing null values, it is important to understand the difference between the way the Equals method evaluates null values in System.Data.SqlTypes as compared with the way it works with CLR types. System.Data.SqlTypesEquals メソッドではすべて、NULL 値の評価にデータベース セマンティクスが使用されます。一方または両方の値が NULL である場合は、比較によって NULL が得られます。All of the System.Data.SqlTypesEquals methods use database semantics for evaluating null values: if either or both of the values is null, the comparison yields null. その一方で、2 つの Equals に対して CLR System.Data.SqlTypes メソッドを使用した場合は、両方が NULL であれば true が得られます。On the other hand, using the CLR Equals method on two System.Data.SqlTypes will yield true if both are null. これは、CLR String.Equals メソッドなどのインスタンス メソッドを使用した場合と、SqlString.Equals などの静的/共有メソッドを使用した場合の違いを反映しています。This reflects the difference between using an instance method such as the CLR String.Equals method, and using the static/shared method, SqlString.Equals.

次のコード サンプルでは、SqlString.Equals メソッドと String.Equals メソッドにそれぞれ NULL 値のペアを渡し、次に空の文字列のペアを渡した場合の、各メソッドの結果の違いを示します。The following example demonstrates the difference in results between the SqlString.Equals method and the String.Equals method when each is passed a pair of null values and then a pair of empty strings.

    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

このコードを実行すると、次の出力が生成されます。The code produces the following output:

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   

関連項目See also