Aracılığıyla paylaş


Null Değerleri İşleme

İlişkisel veritabanındaki null değer, sütundaki değer bilinmediğinde veya eksik olduğunda kullanılır. Null, boş bir dize (karakter veya tarih saat veri türleri için) veya sıfır değeri (sayısal veri türleri için) değildir. ANSI SQL-92 belirtimi, tüm null değerlerin tutarlı bir şekilde işlenmesi için null değerin tüm veri türleri için aynı olması gerektiğini belirtir. System.Data.SqlTypes ad alanı, INullable arabirimini uygulayarak null semantik sağlar. içindeki System.Data.SqlTypes veri türlerinin her biri kendi IsNull özelliğine ve Null bu veri türünün bir örneğine atanabilecek bir değere sahiptir.

Uyarı

.NET Framework sürüm 2.0, programcıların bir değer türünü, temel türdeki tüm değerleri temsil edecek şekilde genişletmesine olanak tanıyan null yapılabilir değer türleri için destek sundu. Bu CLR null atanabilir değer türleri, Nullable yapısının bir örneğini temsil eder. Bu özellik, değer türlerinin kutulanıp açıldığında özellikle kullanışlıdır ve nesne türleriyle daha iyi bir uyumluluk sağlar. CLR boş atanabilir değer türleri, ANSI SQL null değerinin bir null başvurusu ile (veya Visual Basic'te Nothing) aynı şekilde davranmaması nedeniyle veritabanı null değerlerini depolamak için tasarlanmamıştır. Veritabanı ANSI SQL null değerleriyle çalışmak için System.Data.SqlTypes null değerlerini Nullable yerine kullanın. Visual Basic'te null atanabilir değer türleriyle çalışma hakkında daha fazla bilgi için bkz. Null Atanabilir Değer Türleri, C# için bkz. Null atanabilir değer türleri.

Null'lar ve Three-Valued Mantığı

Sütun tanımlarında null değerlere izin vermek, uygulamanıza üç değerli mantık ekler. Karşılaştırma üç koşuldan birini değerlendirebilir:

  • Doğru

  • Yanlış

  • Bilinmiyor

Null değerinin bilinmediği kabul edildiğinden, birbirine kıyasla iki null değeri eşit olarak kabul edilmez. Aritmetik işleçler kullanan ifadelerde işlenenlerden herhangi biri null ise sonuç da null olur.

Nulls ve SqlBoolean

System.Data.SqlTypes öğelerinin herhangi biri arasındaki karşılaştırma bir SqlBoolean döndürür. Her IsNull birinin SqlType işlevi bir SqlBoolean döndürür ve null değerleri denetlemek için kullanılabilir. Aşağıdaki doğruluk tabloları VE, OR ve DEĞİl işleçlerinin null değer varlığında nasıl çalıştığını gösterir. (T=true, F=false ve U=unknown veya null.)

Doğruluk Tablosu

ANSI_NULLS Seçeneğini Anlama

System.Data.SqlTypes , SQL Server'da ANSI_NULLS seçeneğinin açık olduğu zaman ile aynı semantiği sağlar. tüm aritmetik işleçler (+, -, *, /, %), bit düzeyinde işleçler (~, &, |) ve çoğu işlev, işlenenlerden veya bağımsız değişkenlerden hiçbiri null olmadığında null döndürür, IsNull özelliği dışında.

ANSI SQL-92 standardı, WHERE yan tümcesinde columnName = NULL değerini desteklemez. SQL Server'da ANSI_NULLS seçeneği hem veritabanında varsayılan null atanabilirliği hem de null değerlerle karşılaştırmaların değerlendirilmesini denetler. ANSI_NULLS açıksa (varsayılan), IS NULL işleci null değerleri test ederken ifadelerde kullanılmalıdır. Örneğin, ANSI_NULLS açık olduğunda aşağıdaki karşılaştırma her zaman bilinmeyen sonuç verir:

colname > NULL  

Null değer içeren bir değişkenin karşılaştırılması da bilinmeyen sonuçlar verir:

colname > @MyVariable  

Bir null değeri test etmek için IS NULL veya IS NOT NULL koşulunu kullanın. Bu, WHERE yan tümcesine karmaşıklık ekleyebilir. Örneğin, AdventureWorks Customer tablosundaki TerritoryID sütunu null değerlere izin verir. SELECT deyimi, diğerlerine ek olarak null değerleri test etmek için bir IS NULL koşulu içermelidir:

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

SQL Server'da ANSI_NULLS kapalı olarak ayarlarsanız, null ile karşılaştırmak için eşitlik işlecini kullanan ifadeler oluşturabilirsiniz. Ancak, farklı bağlantıların bu bağlantı için null seçenekler ayarlamasını önleyemezsiniz. Bağlantının ANSI_NULLS ayarlarından bağımsız olarak, null değerleri test etmek için IS NULL kullanmak her zaman işe yarar.

ANSI_NULLS kapalı ayarı, içinde null değerleri işlemek için her zaman ANSI SQL-92 standardını izleyen bir DataSetiçinde System.Data.SqlTypesdesteklenmez.

Boş Değerler Atama

Null değerler özeldir ve bunların depolama ve atama semantiği farklı tür sistemleri ve depolama sistemleri arasında farklılık gösterir. A Dataset , farklı tür ve depolama sistemleriyle kullanılacak şekilde tasarlanmıştır.

Bu bölüm, farklı tür sistemleri genelinde bir DataColumn içindeki DataRow'ye null değerler atamanın null semantiğini açıklar.

DBNull.Value
Bu atama herhangi bir DataColumn tür için geçerlidir. Eğer tür INullable uygularsa, DBNull.Value uygun kesin olarak yazılan Null değere zorlanır.

SqlType.Null
Tüm System.Data.SqlTypes veri türleri uygular INullable. Güçlü tiplenmiş null değer, örtük dönüşüm işleçleri kullanılarak sütunun veri türüne dönüştürülebiliyorsa, atama gerçekleştirilmelidir. Aksi takdirde geçersiz bir tür dönüştürme istisnası fırlatılır.

null
'null' verilen DataColumn veri türü için yasal bir değerse, uygun DbNull.Value veya Null türüyle INullable ilişkili (SqlType.Null) dönüştürülür.

derivedUdt.Null
UDT sütunları için null her zaman DataColumn ile ilişkilendirilmiş türe göre depolanır. Alt sınıfı uygulanırken uygulanmayan DataColumn ile ilişkili bir INullable UDT örneğini göz önünde bulundurun. Bu durumda, türetilmiş sınıfla ilişkili kesin belirlenmiş bir null değeri atanırsa, null depolama her zaman DataColumn'un veri türüyle tutarlı olduğundan, tanımsız bir DbNull.Value olarak depolanır.

Uyarı

Nullable<T> veya Nullable yapısı şu anda DataSet içinde desteklenmiyor.

Herhangi bir System.Data.SqlTypes örneğin varsayılan değeri null'tır.

System.Data.SqlTypes içindeki null değerler türe özgüdür ve DbNull gibi tek bir değerle temsil edilemez. IsNull Null değerleri denetlemek için özelliğini kullanın.

Aşağıdaki kod örneğinde gösterildiği gibi null değerler DataColumn öğesine atanabilir. Özel durum tetiklemeden değişkenlere SqlTypes doğrudan null değerler atayabilirsiniz.

Örnek

Aşağıdaki kod örneği, DataTable ve SqlInt32 olarak tanımlanan iki sütun içeren bir SqlString oluşturur. Kod, bilinen bir değer satırı, bir null değer satırı ekler ve daha sonra DataTable üzerinde yinelenerek değerleri değişkenlere atar ve çıktıyı konsol penceresinde görüntüler.

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

Bu örnekte aşağıdaki sonuçlar görüntülenir:

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

Birden Çok Sütun (Satır) Ataması

DataTable.Add, DataTable.LoadDataRow, veya bir satıra eşleştirilen bir ItemArray değeri kabul eden diğer API'ler, 'null' öğesini DataColumn'un varsayılan değerine eşleştirin. Dizideki bir nesne DbNull.Value veya bunun kesin olarak türü belirlenmiş bir karşılığını içeriyorsa, yukarıda açıklanan kurallar aynı şekilde uygulanır.

Ayrıca, null atamaların DataRow.["columnName"] bir örneği için aşağıdaki kurallar geçerlidir:

  1. Varsayılan değer, DbNull.Value kesin olarak yazılan null sütunlar dışında tümü içindir; burada uygun şekilde kesin olarak belirlenmiş null değerdir.

  2. Null değerler, XML dosyalarına seri hale getirme sırasında hiçbir zaman kaydedilmez (XML'de sıkça görülen "xsi:nil" formatında olduğu gibi).

  3. Varsayılan değerler de dahil olmak üzere null olmayan tüm değerler, XML'ye seri hale getirilirken her zaman yazılır. Bu, null değerin (xsi:nil) açık olduğu ve varsayılan değerin örtük olduğu XSD/XML semantiğinden farklı değildir (XML'de yoksa, doğrulayan bir ayrıştırıcı bunu ilişkili bir XSD şemasından alabilir). Bunun tersi bir DataTable için geçerlidir: null değer örtük ve varsayılan değer belirgindir.

  4. XML girişinden okunan satırlar için tüm eksik sütun değerleri NULL olarak atanır. veya benzer yöntemler kullanılarak NewRow oluşturulan satırlara DataColumn'un varsayılan değeri atanır.

  5. IsNull yöntemi, hem true hem de DbNull.Value için INullable.Null döndürür.

Null Değerleri SQL Türleri ve CLR Türleriyle Karşılaştırma

Null değerleri karşılaştırırken, Equals yönteminin System.Data.SqlTypes'deki null değerleri, CLR türleriyle çalışma biçimine kıyasla nasıl değerlendirdiğini anlamak önemlidir. System.Data.SqlTypes Equals Tüm yöntemler null değerleri değerlendirmek için veritabanı semantiğini kullanır: değerlerin biri veya her ikisi de null ise, karşılaştırma null verir. Öte yandan, iki Equals üzerinde CLR System.Data.SqlTypes yönteminin kullanılması, her ikisi de null ise true sonucunu verir. Bu, CLR String.Equals yöntemi gibi bir örnek yöntemi ile statik/paylaşılan yönteminin SqlString.Equalskullanılması arasındaki farkı yansıtır.

Aşağıdaki örnek, SqlString.Equals yöntemi ile String.Equals yöntemi arasındaki sonuç farkını, her birine önce bir çift null değer ve ardından bir çift boş dize geçirildiğinde gösterir.

    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 aşağıdaki çıkışı oluşturur:

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

Ayrıca bakınız