Behandeln von NULL-WertenHandling Null Values

Wenn der Wert in einer Spalte unbekannt ist oder fehlt, wird in einer relationalen Datenbank ein NULL-Wert verwendet.A null value in a relational database is used when the value in a column is unknown or missing. NULL ist weder eine leere Zeichenfolge (für Zeichen- oder Datetime-Datentypen) noch ein Wert 0 (null) (für numerische Datentypen).A null is neither an empty string (for character or datetime data types) nor a zero value (for numeric data types). Die ANSI SQL-92-Spezifikation legt fest, dass NULL für alle Datentypen gleich sein muss, sodass alle NULL-Werte einheitlich behandelt werden können.The ANSI SQL-92 specification states that a null must be the same for all data types, so that all nulls are handled consistently. Der System.Data.SqlTypes-Namespace stellt durch Implementieren der INullable-Schnittstelle eine NULL-Semantik bereit.The System.Data.SqlTypes namespace provides null semantics by implementing the INullable interface. Jeder Datentyp in System.Data.SqlTypes besitzt eine eigene IsNull-Eigenschaft und einen Null-Wert. Diese können einer Instanz dieses Datentyps zugewiesen werden.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.

Hinweis

Neu in .NET Framework 2.0 ist die Unterstützung für Typen, die NULL-Werte zulassen. Programmierer können damit einen Werttyp so erweitern, dass dieser alle Werte des zugrunde liegenden Typs darstellen kann.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. Die CLR-Typen, die NULL-Werte zulassen, stellen eine Instanz der Nullable-Struktur dar.These CLR nullable types represent an instance of the Nullable structure. Diese Funktion erweist sich vor allem dann als hilfreich, wenn Werttypen geschachtelt und nicht geschachtelt sind, wodurch sich die Kompatibilität mit Objekttypen verbessert.This capability is especially useful when value types are boxed and unboxed, providing enhanced compatibility with object types. CLR-Typen, die NULL-Werte zulassen, sind nicht zum Speichern von Datenbank-NULL-Werten gedacht, weil sich ein ANSI-SQL-NULL-Wert anders als ein null-Verweis (oder Nothing in Visual Basic) verhält.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). Verwenden Sie zum Arbeiten mit ANSI SQL-Datenbank-NULL-Werten statt System.Data.SqlTypes lieber Nullable-NULL-Werte.For working with database ANSI SQL null values, use System.Data.SqlTypes nulls rather than Nullable. Weitere Informationen zum Arbeiten mit CLR- Typen, die NULL-Werte zulassen, C# finden SieVisual Basic unter.For more information on working with CLR nullable types in Visual Basic see Nullable Value Types, and for C# see Using nullable value types.

NULL-Werte und dreiwertige LogikNulls and Three-Valued Logic

Wenn in Spaltendefinitionen NULL-Werte zugelassen werden, wird dreiwertige Logik in die Anwendung eingeführt.Allowing null values in column definitions introduces three-valued logic into your application. Eine Vergleichsoperation wird mit einer der drei nachfolgenden Bedingungen ausgewertet:A comparison can evaluate to one of three conditions:

  • TrueTrue

  • FalseFalse

  • UnbekanntUnknown

Da NULL als unbekannt betrachtet wird, gelten zwei miteinander verglichene NULL-Werte nicht als gleich.Because null is considered to be unknown, two null values compared to each other are not considered to be equal. In Ausdrücken, die arithmetische Operatoren verwenden, ist das Ergebnis NULL, wenn einer der Operanden NULL ist.In expressions using arithmetic operators, if any of the operands is null, the result is null as well.

NULL-Werte und SqlBooleanNulls and SqlBoolean

Ein Vergleich zwischen beliebigen System.Data.SqlTypes gibt einen SqlBoolean zurück.Comparison between any System.Data.SqlTypes will return a SqlBoolean. Die IsNull-Funktion für jeden SqlType gibt einen SqlBoolean-Wert zurück und kann dazu verwendet werden, das Vorhandensein von NULL-Werten zu überprüfen.The IsNull function for each SqlType returns a SqlBoolean and can be used to check for null values. Den folgenden Tabellen mit Wahrheitswerten können Sie entnehmen, wie die Operatoren AND, OR und NOT bei Vorhandensein eines NULL-Werts funktionieren.The following truth tables show how the AND, OR, and NOT operators function in the presence of a null value. (T=true (wahr), F=false (falsch) und U=unknown (unbekannt) oder NULL.)(T=true, F=false, and U=unknown, or null.)

WahrheitstabelleTruth Table

Informationen zur ANSI_NULLS-OptionUnderstanding the ANSI_NULLS Option

Mit System.Data.SqlTypes wird dieselbe Semantik bereitgestellt wie bei aktivierter ANSI_NULLS-Option in SQL Server.System.Data.SqlTypes provides the same semantics as when the ANSI_NULLS option is set on in SQL Server. Alle arithmetischen Operatoren (+,-, *,/,%), bitweise Operatoren (~, &, |) und die meisten Funktionen geben NULL zurück, wenn einer der Operanden oder Argumente NULL ist, mit Ausnahme der-Eigenschaft IsNull.All arithmetic operators (+, -, *, /, %), bitwise operators (~, &, |), and most functions return null if any of the operands or arguments is null, except for the property IsNull.

Der ANSI SQL-92-Standard unterstützt ColumnName = NULL in einer WHERE-Klausel nicht.The ANSI SQL-92 standard does not support columnName = NULL in a WHERE clause. In SQL Server steuert die ANSI_NULLS-Option die Fähigkeit, in der Standardeinstellung NULL-Werte in der Datenbank zuzulassen sowie die Auswertung von Vergleichen mit NULL-Werten.In SQL Server, the ANSI_NULLS option controls both default nullability in the database and evaluation of comparisons against null values. Wenn ANSI_NULLS aktiviert ist (Standardeinstellung), muss der IS NULL-Operator beim Testen auf NULL-Werte in Ausdrücken verwendet werden.If ANSI_NULLS is turned on (the default), the IS NULL operator must be used in expressions when testing for null values. Der folgende Vergleich ergibt z. B. immer "Unknown", wenn ANSI_NULLS aktiviert ist:For example, the following comparison always yields unknown when ANSI_NULLS is on:

colname > NULL  

Der Vergleich mit einer Variablen, die einen NULL-Wert enthält, ergibt auch "Unknown":Comparison to a variable containing a null value also yields unknown:

colname > @MyVariable  

Verwenden Sie zum Testen auf einen NULL-Wert das IS NULL-Prädikat oder das IS NOT NULL-Prädikat.Use the IS NULL or IS NOT NULL predicate to test for a null value. Dies kann die Komplexität der WHERE-Klausel erhöhen.This can add complexity to the WHERE clause. Die TerritoryID-Spalte in der AdventureWorks Customer-Tabelle lässt z. B. NULL-Werte zu.For example, the TerritoryID column in the AdventureWorks Customer table allows null values. Wenn eine SELECT-Anweisung zusätzlich zu anderen Werten auf NULL-Werte getestet werden soll, muss sie ein IS NULL-Prädikat enthalten: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  

Wenn Sie in SQL Server ANSI_NULLS deaktivieren, können Sie Ausdrücke erstellen, die mithilfe des Gleichheitsoperators einen Vergleich mit NULL durchführen.If you set ANSI_NULLS off in SQL Server, you can create expressions that use the equality operator to compare to null. Sie können jedoch nicht verhindern, dass verschiedene Verbindungen NULL-Optionen für diese Verbindung festlegen.However, you can't prevent different connections from setting null options for that connection. Die Verwendung von IS NULL funktioniert zum Testen auf NULL-Werte immer, unabhängig von den für eine Verbindung festgelegten ANSI_NULLS-Einstellungen.Using IS NULL to test for null values always works, regardless of the ANSI_NULLS settings for a connection.

Die Deaktivierung von ANSI_NULLS wird in einem DataSet nicht unterstützt. Dieses befolgt immer den ANSI SQL-92-Standard für die Behandlung von NULL-Werten in System.Data.SqlTypes.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.

Zuweisen von NULL-WertenAssigning Null Values

NULL-Werte weisen einige Besonderheiten auf und ihre Speicherung und Zuweisungssemantik ist in verschiedenen Typ- und Speichersystemen unterschiedlich.Null values are special, and their storage and assignment semantics differ across different type systems and storage systems. Ein Dataset ist für die Verwendung mit verschiedenen Typ- und Speichersystemen vorgesehen.A Dataset is designed to be used with different type and storage systems.

In diesem Abschnitt wird die NULL-Semantik zum Zuweisen von NULL-Werten zu einer DataColumn in einer DataRow in den verschiedenen Typsystemen beschrieben.This section describes the null semantics for assigning null values to a DataColumn in a DataRow across the different type systems.

DBNull.Value
Diese Zuweisung ist für eine DataColumn eines beliebigen Typs gültig.This assignment is valid for a DataColumn of any type. Wenn der Typ INullable implementiert, wird DBNull.Value in den entsprechenden stark typisierten NULL-Wert umgewandelt.If the type implements INullable, DBNull.Value is coerced into the appropriate strongly typed Null value.

SqlType.Null
Alle System.Data.SqlTypes-Datentypen implementieren INullable.All System.Data.SqlTypes data types implement INullable. Wenn der stark typisierte NULL-Wert mit impliziten Umwandlungsoperatoren in den Datentyp der Spalte umgewandelt werden kann, sollte die Zuweisung durchgeführt werden können.If the strongly typed null value can be converted into the column's data type using implicit cast operators, the assignment should go through. Andernfalls wird eine Ausnahme für eine ungültige Umwandlung ausgelöst.Otherwise an invalid cast exception is thrown.

null
Wenn 'NULL' ein zulässiger Wert für den angegebenen DataColumn-Datentyp ist, wird er in den entsprechenden DbNull.Value oder Null umgewandelt, der dem INullable-Typ (SqlType.Null) zugeordnet ist.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
Bei UDT-Spalten werden NULL-Werte immer auf der Grundlage des Typs gespeichert, der der DataColumn zugeordnet ist.For UDT columns, nulls are always stored based on the type associated with the DataColumn. Nehmen wir einen UDT, der einer DataColumn zugeordnet ist und der INullable im Gegensatz zu seiner Unterklasse nicht implementiert.Consider the case of a UDT associated with a DataColumn that does not implement INullable while its sub-class does. In diesem Fall wird er als nicht typisierter DbNull.Value gespeichert, wenn ein stark typisierter NULL-Wert zugewiesen wird, der der abgeleiteten Klasse zugeordnet ist, da die Speicherung von NULL-Werten immer mit dem Datentyp der DataColumn konsistent ist.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.

Hinweis

Die Nullable<T>-Struktur und die Nullable-Struktur werden im DataSet derzeit nicht unterstützt.The Nullable<T> or Nullable structure is not currently supported in the DataSet.

Zuweisung mehrerer Spalten (Zeilen)Multiple Column (Row) Assignment

DataTable.Add, DataTable.LoadDataRow oder andere APIs, die ein ItemArray akzeptieren, das einer Reihe zugeordnet wird, ordnen dem Standardwert der <legacyBold>DataColumn</legacyBold> 'NULL' zu.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. Wenn ein Objekt im Array DbNull.Value oder dessen stark typisierte Entsprechung enthält, gelten dieselben Regeln wie oben beschrieben.If an object in the array contains DbNull.Value or its strongly typed counterpart, the same rules as described above are applied.

Darüber hinaus gelten für Instanzen von DataRow.["columnName"]-NULL-Zuweisungen die folgenden Regeln:In addition, the following rules apply for an instance of DataRow.["columnName"] null assignments:

  1. Der Standard mäßige Standardwert ist DbNull.Value für alle außer den stark typisierten NULL-Spalten, bei denen es sich um den entsprechenden stark typisierten NULL-Wert handelt.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. NULL-Werte werden bei der Serialisierung in XML-Dateien (wie in "xsi:nil") nie ausgegeben.Null values are never written out during serialization to XML files (as in "xsi:nil").

  3. Alle Nicht-NULL-Werte einschließlich der Standardwerte werden bei der Serialisierung nach XML immer ausgegeben.All non-null values, including defaults, are always written out while serializing to XML. Dies entspricht nicht der XSD/XML-Semantik, bei der ein NULL-Wert (xsi:nil) explizit und der Standardwert implizit ist (wenn nicht in XML vorhanden, kann der Wert von einem validierenden Parser aus einem zugeordneten XSD-Schema abgerufen werden).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). Das Gegenteil gilt für eine DataTable: Ein NULL-Wert ist implizit, und der Standardwert ist explizit.The opposite is true for a DataTable: a null value is implicit and the default value is explicit.

  4. Allen fehlenden Spaltenwerten für Zeilen, die aus der XML-Eingabe gelesen werden, wird NULL zugewiesen.All missing column values for rows read from XML input are assigned NULL. Zeilen, die mithilfe von NewRow oder ähnlichen Methoden erstellt wurden, wird der Standardwert von DataColumn zugewiesen.Rows created using NewRow or similar methods are assigned the DataColumn's default value.

  5. Die IsNull-Methode gibt sowohl für true als auch für DbNull.Value``INullable.Null zurück.The IsNull method returns true for both DbNull.Value and INullable.Null.

Zuweisen von NULL-WertenAssigning Null Values

Der Standardwert für alle System.Data.SqlTypes-Instanzen ist NULL.The default value for any System.Data.SqlTypes instance is null.

NULL-Werte in System.Data.SqlTypes sind typspezifisch und können nicht von einem einzelnen Wert (z. B. DbNull) dargestellt werden.Nulls in System.Data.SqlTypes are type-specific and cannot be represented by a single value, such as DbNull. Mit der IsNull-Eigenschaft können Sie überprüfen, ob NULL-Werte vorliegen.Use the IsNull property to check for nulls.

NULL-Werte können einer DataColumn wie im folgenden Codebeispiel dargestellt zugewiesen werden.Null values can be assigned to a DataColumn as shown in the following code example. Sie können SqlTypes-Variablen direkt NULL-Werte zuweisen, ohne eine Ausnahme auszulösen.You can directly assign null values to SqlTypes variables without triggering an exception.

BeispielExample

Im folgenden Codebeispiel wird eine DataTable mit zwei Spalten erstellt, die als SqlInt32 und SqlString definiert werden.The following code example creates a DataTable with two columns defined as SqlInt32 and SqlString. Der Code fügt eine Zeile mit bekannten Werten und eine Zeile mit NULL-Werten hinzu und durchläuft dann die DataTable. Dabei werden den Variablen die Werte zugewiesen und die Ausgabe im Konsolenfenster angezeigt.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

In diesem Beispiel werden die folgenden Ergebnisse angezeigt:This example displays the following results:

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

Vergleichen von NULL-Werten mit "SqlTypes" und CLR-TypenComparing Null Values with SqlTypes and CLR Types

Beim Vergleichen von NULL-Werten ist es wichtig zu verstehen, wie die Equals-Methode NULL-Werte in System.Data.SqlTypes auswertet und wie sie im Unterschied dazu bei CLR-Typen vorgeht.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. Alle System.Data.SqlTypesEquals-Methoden verwenden für die Auswertung von NULL-Werten die Datenbanksemantik: Wenn mindestens einer der Werte NULL ist, ergibt der Vergleich 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. Andererseits ergibt die Anwendung der CLR-Equals-Methode auf zwei System.Data.SqlTypes <legacyBold>true</legacyBold>, wenn beide NULL sind.On the other hand, using the CLR Equals method on two System.Data.SqlTypes will yield true if both are null. Dies spiegelt den Unterschied zwischen der Verwendung einer Instanzmethode wie der CLR-String.Equals-Methode und der Verwendung der <legacyBold>static</legacyBold>/<legacyBold>shared</legacyBold>-Methode SqlString.Equals wider.This reflects the difference between using an instance method such as the CLR String.Equals method, and using the static/shared method, SqlString.Equals.

Das folgende Beispiel zeigt den Unterschied in den Ergebnissen zwischen der SqlString.Equals-Methode und der String.Equals-Methode, wenn beiden Methoden ein Paar von NULL-Werten und dann ein Paar leerer Zeichenfolgen übergeben wird.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

Der Code erzeugt die folgende Ausgabe: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   

Siehe auchSee also