Bagikan melalui


Menangani nilai null

Mengunduh ADO.NET

Nilai null dalam database relasional digunakan ketika nilai dalam kolom tidak diketahui atau hilang. Null bukanlah string kosong (untuk jenis data karakter atau datetime) atau nilai nol (untuk jenis data numerik). Spesifikasi ANSI SQL-92 menyatakan bahwa null harus sama untuk semua jenis data, sehingga semua null ditangani secara konsisten. Namespace System.Data.SqlTypes menyediakan semantik null dengan mengimplementasikan antarmuka INullable. Setiap jenis data di System.Data.SqlTypes memiliki properti IsNull sendiri dan nilai Null yang dapat ditetapkan ke instans jenis data tersebut.

Catatan

.NET Framework versi 2.0 dan .NET Core versi 1.0 memperkenalkan dukungan untuk jenis nullable, yang memungkinkan programmer memperluas jenis nilai untuk mewakili semua nilai dari jenis yang mendasar. Jenis clr nullable ini mewakili instans Nullable struktur. Kemampuan ini sangat berguna ketika jenis nilai dikotak dan tidak dikotak, memberikan peningkatan kompatibilitas dengan jenis objek. Jenis clr nullable tidak ditujukan untuk penyimpanan database null karena ANSI SQL null tidak bertingkah sama seperti null referensi (atau Nothing di Visual Basic). Untuk bekerja dengan nilai null database ANSI SQL, gunakan System.Data.SqlTypes null dan bukan Nullable. Untuk informasi selengkapnya tentang bekerja dengan jenis clr nullable di C# lihat Jenis Nullable, dan untuk C# lihat Menggunakan Jenis Nullable.

Logika null dan tiga nilai

Mengizinkan nilai null dalam definisi kolom memperkenalkan logika tiga nilai ke dalam aplikasi Anda. Perbandingan dapat mengevaluasi salah satu dari tiga kondisi:

  • Benar

  • Salah

  • Tidak dikenal

Karena null dianggap tidak diketahui, dua nilai null dibandingkan satu sama lain tidak dianggap sama. Dalam ekspresi yang menggunakan operator aritmatika, jika salah satu operan adalah null, hasilnya juga null.

Nulls dan SqlBoolean

Perbandingan antara System.Data.SqlTypes mana pun akan menghasilkan SqlBoolean. Fungsi IsNull untuk setiap SqlType mengembalikan SqlBoolean dan dapat digunakan untuk memeriksa nilai null. Tabel kebenaran berikut menunjukkan cara operator AND, OR, dan NOT berfungsi dengan adanya nilai null. (T=true, F=false, dan U=unknown, atau null.)

Tabel Kebenaran

Memahami opsi ANSI_NULLS

System.Data.SqlTypes memberikan semantik yang sama seperti saat opsi ANSI_NULLS diaktifkan di SQL Server. Semua operator aritmatika (+, -, *, /, %), operator bitwise (~, &, |), dan sebagian besar fungsi mengembalikan null jika salah satu operand atau argumen null, kecuali untuk properti IsNull.

Standar ANSI SQL-92 tidak mendukung columnName = NULL dalam klausa WHERE. Di SQL Server, opsi ANSI_NULLS mengontrol nullabilitas default dalam database dan evaluasi perbandingan terhadap nilai null. Jika ANSI_NULLS diaktifkan (default), operator IS NULL harus digunakan dalam ekspresi saat menguji nilai null. Misalnya, perbandingan berikut selalu menghasilkan unknwon saat ANSI_NULLS aktif:

colname > NULL  

Perbandingan dengan variabel yang berisi nilai null juga menghasilkan unknown:

colname > @MyVariable  

Gunakan predikat IS NULL atau IS NOT NULL untuk menguji nilai null. Predikat ini dapat menambah kerumitan pada klausa WHERE. Misalnya, kolom TerritoryID di tabel Pelanggan AdventureWorks memungkinkan nilai null. Jika pernyataan SELECT adalah untuk menguji nilai null selain yang lain, pernyataan ini harus menyertakan predikat IS NULL:

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

Jika Anda menonaktifkan ANSI_NULLS di SQL Server, Anda dapat membuat ekspresi yang menggunakan operator persamaan untuk membandingkan dengan null. Namun, Anda tidak dapat mencegah koneksi yang berbeda dari pengaturan opsi null untuk koneksi tersebut. Menggunakan IS NULL untuk menguji nilai null selalu berhasil, terlepas dari pengaturan ANSI_NULLS untuk koneksi.

Menonaktifkan ANSI_NULLS tidak didukung di DataSet, yang selalu mengikuti standar ANSI SQL-92 untuk menangani nilai null di System.Data.SqlTypes.

Menetapkan nilai null

Nilai null adalah khusus, dan semantik penyimpanan dan penugasannya berbeda di berbagai jenis sistem dan sistem penyimpanan. Dataset dirancang untuk digunakan dengan jenis dan sistem penyimpanan yang berbeda.

Bagian ini menjelaskan semantik null untuk menetapkan nilai null ke DataColumn di DataRow di berbagai jenis sistem.

DBNull.Value
Penetapan ini berlaku untuk DataColumn jenis apa pun. Jika jenis mengimplementasikan INullable, DBNull.Value dipaksa menjadi nilai Null yang berjenis dengan kuat dan sesuai.

SqlType.Null
Semua System.Data.SqlTypes jenis data menerapkan INullable. Jika nilai null yang berjenis dengan kuat dapat dikonversi menjadi jenis data kolom menggunakan operator konversi implisit, penetapan harus dilakukan. Jika tidak, pengecualian konversi eksplisit yang tidak valid akan ditampilkan.

null
Jika 'null' adalah nilai legal untuk jenis data DataColumn yang diberikan, nilai tersebut akan dipaksakan ke dalam DbNull.Value atau Null yang terkait dengan jenis INullable (SqlType.Null)

derivedUdt.Null
Untuk kolom UDT, null selalu disimpan berdasarkan jenis yang terkait dengan DataColumn. Pertimbangkan kasus UDT yang terkait dengan DataColumn yang tidak mengimplementasikan INullable sementara sub-kelasnya melakukannya. Dalam kasus ini, jika nilai null yang berjenis kuat terkait dengan kelas turunan ditetapkan, nilai tersebut disimpan sebagai DbNull.Value yang tidak berjenis, karena penyimpanan null selalu konsisten dengan jenis data Kolom Data.

Catatan

Struktur Nullable<T> atau Nullable saat ini tidak didukung di DataSet.

Penetapan beberapa kolom (baris)

DataTable.Add, DataTable.LoadDataRow, atau API lain yang menerima ItemArray yang dipetakan ke baris, memetakan 'null' ke nilai default DataColumn. Jika objek dalam larik berisi DbNull.Value atau pasangannya yang berjenis dengan kuat, aturan yang sama seperti yang dijelaskan di atas akan diterapkan.

Selain itu, aturan berikut berlaku untuk instans DataRow.["columnName"] penetapan null:

  • Nilai default default adalah DbNull.Value untuk semua kecuali kolom null yang diketik dengan kuat di mana itu adalah nilai null yang diketik dengan kuat yang sesuai.

  • Nilai null tidak pernah ditulis selama serialisasi ke file XML (seperti dalam "xsi:nil").

  • Semua nilai non-null, termasuk default, selalu ditulis saat membuat serial ke XML. Operasi ini tidak seperti semantik XSD/XML ketika nilai null (xsi:nil) eksplisit dan nilai default-nya implisit (jika tidak ada dalam XML, parser yang memvalidasi bisa mendapatkannya dari skema XSD terkait). Kebalikannya berlaku untuk DataTable: nilai null adalah implisit dan nilai default-nya adalah eksplisit.

  • Semua nilai kolom yang hilang untuk baris yang dibaca dari input XML ditetapkan NULL. Baris yang dibuat menggunakan NewRow atau metode serupa diberi nilai default DataColumn.

  • Metode IsNull mengembalikan true untuk DbNull.Value dan INullable.Null.

Menetapkan nilai null ke SqlTypes

Nilai default untuk setiap instans System.Data.SqlTypes adalah null.

Null di System.Data.SqlTypes adalah jenis khusus dan tidak dapat diwakili oleh nilai tunggal, seperti DbNull. Gunakan properti IsNull untuk memeriksa null.

Nilai null dapat ditetapkan ke DataColumn seperti yang ditunjukkan pada contoh kode berikut. Anda dapat langsung menetapkan nilai null ke variabel SqlTypes tanpa memicu pengecualian.

Contoh

Contoh kode berikut membuat DataTable dengan dua kolom yang didefinisikan sebagai SqlInt32 dan SqlString. Kode menambahkan satu baris nilai yang diketahui, satu baris nilai null dan kemudian beralih melalui DataTable, menetapkan nilai ke variabel dan menampilkan output di jendela konsol.

using Microsoft.Data.SqlClient;
using System.Data.SqlTypes;

class Program
{
    static void Main()
    {
        WorkWithSqlNulls();
        Console.ReadLine();
    }
    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();
        }
    }
}

Contoh ini menampilkan hasil berikut:

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

Membandingkan nilai null dengan jenis SqlTypes dan CLR

Saat membandingkan nilai null, penting untuk memahami perbedaan antara cara metode Equals mengevaluasi nilai null di System.Data.SqlTypes dibandingkan dengan cara kerjanya dengan jenis CLR. Semua metode System.Data.SqlTypesEquals menggunakan semantik basis data untuk mengevaluasi nilai null: jika salah satu atau kedua nilai adalah null, perbandingan akan menghasilkan null. Di sisi lain, menggunakan metode CLR Equals pada dua System.Data.SqlTypes akan menghasilkan true jika keduanya null. Operasi ini mencerminkan perbedaan antara menggunakan metode instans seperti metode CLR String.Equals, dan menggunakan metode statis/bersama, SqlString.Equals.

Contoh berikut menunjukkan perbedaan hasil antara metode SqlString.Equals dan metode String.Equals ketika masing-masing melewati sepasang nilai null dan kemudian sepasang string yang kosong.

using System.Data.SqlTypes;

namespace SqlNullsCS
{
    class Program
    {
        static void Main()
        {
            CompareNulls();
            Console.ReadLine();
        }
        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;
        }
    }
}

Kode menghasilkan output berikut:

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   

Langkah berikutnya