Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wartość null w relacyjnej bazie danych jest używana, gdy wartość w kolumnie jest nieznana lub brakuje jej. Wartość null nie jest ciągiem pustym (dla typów danych znaków lub daty/godziny) ani wartością zerową (dla typów danych liczbowych). Specyfikacja ANSI SQL-92 stwierdza, że wartość null musi być taka sama dla wszystkich typów danych, dzięki czemu wszystkie wartości null są obsługiwane spójnie.
System.Data.SqlTypes Przestrzeń nazw zapewnia semantykę null poprzez zaimplementowanie interfejsu INullable. Każdy z typów danych w System.Data.SqlTypes ma własną IsNull
właściwość i wartość Null
, którą można przypisać do wystąpienia tego typu danych.
Uwaga / Notatka
Program .NET Framework w wersji 2.0 wprowadził obsługę typów wartości dopuszczających wartość null, co umożliwia programistom rozszerzenie typu wartości w celu reprezentowania wszystkich wartości bazowego typu. Typy wartości dopuszczalne CLR reprezentują wystąpienie struktury Nullable. Ta funkcja jest szczególnie przydatna, gdy typy wartości są opakowywane i odpakowywane, co zapewnia lepszą zgodność z typami obiektów. Typy wartości dopuszczające wartość null w CLR nie są przeznaczone do przechowywania wartości null bazy danych, ponieważ wartość null w ANSI SQL nie zachowuje się tak samo jak referencja null
(lub Nothing
w Visual Basic). Aby pracować z wartościami null baz danych SQL ANSI, użyj System.Data.SqlTypes wartości null, a nie Nullable. Aby uzyskać więcej informacji na temat pracy z typami wartości nullable CLR w języku Visual Basic, zobacz Typy wartości nullable, a w przypadku języka C# zobacz Typy wartości nullable.
Wartości null i logika Three-Valued
Zezwalanie na wartości null w definicjach kolumn wprowadza do aplikacji trzywartą logikę. Porównanie może ocenić jeden z trzech warunków:
Prawda
Nieprawda
Nieznany
Ponieważ wartość null jest uważana za nieznaną, dwie wartości null w porównaniu ze sobą nie są uważane za równe. W wyrażeniach używających operatorów arytmetycznych, jeśli którykolwiek z operandów ma wartość null, wynik ma również wartość null.
Wartości null i SqlBoolean
Porównanie między dowolnym System.Data.SqlTypes elementem zwróci wartość SqlBoolean. Funkcja IsNull
dla każdego SqlType
zwraca SqlBoolean i może służyć do sprawdzania wartości null. W poniższych tabelach prawdy pokazano, jak operatory AND, OR i NOT działają w obecności wartości null. (T=true, F=false i U=unknown lub null).
Opis opcji ANSI_NULLS
System.Data.SqlTypes udostępnia te same semantyki co w przypadku ustawienia opcji ANSI_NULLS w programie SQL Server. Wszystkie operatory arytmetyczne (+, -, *, /, %), operatory bitowe (~, &, |) i większość funkcji zwracają wartość null, jeśli którykolwiek z operandów lub argumentów ma wartość null, z wyjątkiem właściwości IsNull
.
Standard ANSI SQL-92 nie obsługuje kolumny columnName = NULL w klauzuli WHERE. W programie SQL Server opcja ANSI_NULLS kontroluje zarówno domyślną wartość null w bazie danych, jak i ocenę porównań z wartościami null. Jeśli ANSI_NULLS jest włączona (wartość domyślna), operator IS NULL musi być używany w wyrażeniach podczas testowania wartości null. Na przykład następujące porównanie zawsze zwraca wartość nieznaną, gdy ANSI_NULLS jest włączona:
colname > NULL
Porównanie ze zmienną zawierającą wartość null również daje rezultat nieznany.
colname > @MyVariable
Użyj predykatu IS NULL lub IS NOT NULL, aby przetestować wartość null. Może to zwiększyć złożoność klauzuli WHERE. Na przykład kolumna TerritoryID w tabeli AdventureWorks Customer zezwala na wartości null. Jeśli instrukcja SELECT ma testować wartości null oprócz innych, musi zawierać predykat IS NULL:
SELECT CustomerID, AccountNumber, TerritoryID
FROM AdventureWorks.Sales.Customer
WHERE TerritoryID IN (1, 2, 3)
OR TerritoryID IS NULL
Jeśli ustawisz ANSI_NULLS wyłączone w programie SQL Server, możesz utworzyć wyrażenia, które używają operatora równości do porównania z wartością null. Nie można jednak uniemożliwić innym połączeniom ustawiania opcji null dla tego połączenia. Używanie IS NULL do sprawdzenia wartości null zawsze jest skuteczne, niezależnie od ustawień ANSI_NULLS dla połączenia.
Ustawienie opcji ANSI_NULLS na wyłączone nie jest obsługiwane w DataSet
, który zawsze przestrzega standardu ANSI SQL-92 do obsługi wartości null w System.Data.SqlTypes.
Przypisywanie wartości null
Wartości null są szczególne, a ich semantyka przechowywania i przypisywania różni się w zależności od różnych systemów typów i systemów przechowywania. Element jest Dataset
przeznaczony do użycia z różnymi typami i systemami przechowywania.
W tej sekcji opisano semantykę wartości null przy przypisywaniu wartości null do elementu DataColumn w różnych systemach typów DataRow.
DBNull.Value
To przypisanie jest prawidłowe dla DataColumn
dowolnego typu. Jeśli typ implementuje INullable
, DBNull.Value
jest przekształcany w odpowiednią silnie typizowaną wartość null.
SqlType.Null
Wszystkie System.Data.SqlTypes typy danych implementują INullable
. Jeśli wartość null o silnym typowaniu może być przekonwertowana na typ danych kolumny przy użyciu operatorów rzutowania niejawnych, przypisanie powinno zostać wykonane. W przeciwnym razie jest zgłaszany nieprawidłowy wyjątek rzutu.
null
Jeśli wartość "null" jest wartością prawną dla danego DataColumn
typu danych, jest ona zmuszana do odpowiedniego DbNull.Value
lub Null
skojarzonego z typem INullable
(SqlType.Null
)
derivedUdt.Null
W przypadku kolumn UDT wartości null są zawsze przechowywane zgodnie z typem skojarzonym z DataColumn
. Rozważmy przypadek UDT skojarzonego z elementem DataColumn
, który nie implementuje INullable
, podczas gdy jego podklasa to robi. W takim przypadku, jeśli silnie typizowana wartość null połączona z klasą pochodną jest przypisana, jest przechowywana jako nietypizowana DbNull.Value
, ponieważ przechowywanie wartości null jest zawsze zgodne z typem danych DataColumn.
Uwaga / Notatka
Struktura Nullable<T>
lub Nullable nie jest obecnie obsługiwana w pliku DataSet
.
Wartość domyślna dla dowolnego System.Data.SqlTypes wystąpienia ma wartość null.
Wartości null w obiekcie System.Data.SqlTypes są specyficzne dla typu i nie mogą być reprezentowane przez jedną wartość, taką jak DbNull
. Użyj właściwości , IsNull
aby sprawdzić, czy nie ma wartości null.
Wartości null można przypisać do elementu , DataColumn jak pokazano w poniższym przykładzie kodu. Możesz bezpośrednio przypisać wartości null do SqlTypes
zmiennych bez wyzwalania wyjątku.
Przykład
Poniższy przykład kodu tworzy obiekt DataTable z dwiema kolumnami zdefiniowanymi jako SqlInt32 i SqlString. Kod dodaje jeden wiersz znanych wartości, jeden wiersz wartości null, a następnie iteruje za pośrednictwem DataTable, przypisując wartości do zmiennych i wyświetlając dane wyjściowe w oknie konsoli.
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
W tym przykładzie zostaną wyświetlone następujące wyniki:
isColumnNull=False, ID=123, Description=Side Mirror
isColumnNull=True, ID=Null, Description=Null
Przypisanie wielu kolumn (wierszy)
DataTable.Add
, DataTable.LoadDataRow
, lub inne interfejsy API, które akceptują element ItemArray, który jest przypisywany do wiersza, przypisują wartość 'null' na wartość domyślną kolumny DataColumn. Jeśli obiekt w tablicy zawiera DbNull.Value
lub jego silnie typizowane odpowiedniki, stosowane są te same reguły, co opisane powyżej.
Ponadto dla wystąpienia DataRow.["columnName"]
przypisań o wartości null obowiązują następujące reguły:
Wartość domyślna dotyczy
DbNull.Value
wszystkich z wyjątkiem silnie typizowanych kolumn null, gdzie jest to odpowiednia silnie typizowana wartość null.Wartości null nigdy nie są zapisywane podczas serializacji do plików XML (jak w pliku "xsi:nil").
Wszystkie wartości inne niż null, w tym wartości domyślne, są zawsze zapisywane podczas serializacji do formatu XML. Jest to w przeciwieństwie do semantyki XSD/XML, gdzie wartość null (xsi:nil) jest jawna, a wartość domyślna jest niejawna (jeśli nie istnieje w formacie XML, analizator sprawdzania poprawności może pobrać go ze skojarzonego schematu XSD). Jest odwrotnie w przypadku
DataTable
: wartość null jest niejawna, a wartość domyślna jest jawna.Wszystkie brakujące wartości kolumn dla wierszy odczytanych z danych wejściowych XML mają przypisaną wartość NULL. Do wartości domyślnej kolumny DataColumn są przypisywane wiersze utworzone przy użyciu NewRow lub podobne metody.
Metoda IsNull zwraca
true
zarówno dlaDbNull.Value
, jak i dlaINullable.Null
.
Porównywanie wartości null z typami SqlTypes i CLR
Podczas porównywania wartości null ważne jest, aby zrozumieć różnicę między sposobem, w jaki metoda Equals
ocenia wartości null w System.Data.SqlTypes, a sposobem, w jaki działa z typami CLR.
System.Data.SqlTypes
Equals
Wszystkie metody używają semantyki bazy danych do obliczania wartości null: jeśli jedna lub obie wartości mają wartość null, porównanie daje wartość null. Z drugiej strony użycie metody CLR Equals
na dwóch System.Data.SqlTypes zwróci wartość true, jeśli oba mają wartość null. Odzwierciedla to różnicę między użyciem metody wystąpienia, takiej jak metoda CLRString.Equals
, a użyciem metody statycznej/udostępnionej. SqlString.Equals
W poniższym przykładzie pokazano różnicę w wynikach między metodą SqlString.Equals
a metodą String.Equals
, gdy każda z nich otrzymuje parę wartości null, a następnie parę pustych ciągów znaków.
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
Kod generuje następujące dane wyjściowe:
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