DBNull和Null的区别

网络整理 - 08-18

   DBNull 类

  表示不存在的值。无法继承此类。

  命名空间: System

  程序集: mscorlib(在 mscorlib.dll 中)

  DBNull 类表示一个不存在的值。例如,在数据库的表中,某一行的某列中可能不包含任何数据。即,该列被视为根本不存在,而不只是没有值。一个表示不存在的列的 DBNull 对象。此外,COM 互操作使用 DBNull 类来区分 VT_NULL 变量(指示不存在的值)和 VT_EMPTY 变量(指示未指定的值)。

  DBNull 类型是一个单独的类,这意味着只有一个 DBNull 对象存在。DBNull::.Value 成员表示唯一的 DBNull对象。DBNull::.Value 可用于将不存在的值显式分配给数据库字段,但大多数 ADO.NET 数据提供程序在字段没有有效值时会自动分配 DBNull 值。您可以通过将从数据库字段检索到的值传递给 DBNull.Value.Equals 方法,确定该字段值是否为 DBNull 值。然而,有些语言和数据库对象提供一些方法,可以更容易地确定数据库字段值是否为 DBNull::.Value.这些方法包括 Visual Basic 的 IsDBNull 函数、Convert::.IsDBNull 方法、DataTableReader::.IsDBNull 方法和 IDataRecord::.IsDBNull 方法。

  请勿将面向对象的编程语言中的 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 概念与 DBNull对象混淆。在面向对象的编程语言中,nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 表示不存在对某个对象的引用。DBNull 则表示未初始化的变量或不存在的数据库列。

  备注

  示例

  下面的示例调用 DBNull.Value.Equals 方法,来确定联系人数据库中的数据库字段是否具有有效值。如果具有有效值,字段值将被追加到在标签中输出的字符串中。

  C# 中的用法

  private void OutputLabels(DataTable dt)

  {

  string label;

  // Iterate rows of table

  foreach (DataRow row in dt.Rows)

  {

  int labelLen;

  label = String.Empty;

  label += AddFieldValue(label, row, "Title");

  label += AddFieldValue(label, row, "FirstName");

  label += AddFieldValue(label, row, "MiddleInitial");

  label += AddFieldValue(label, row, "LastName");

  label += AddFieldValue(label, row, "Suffix");

  label += "/n";

  label += AddFieldValue(label, row, "Address1");

  label += AddFieldValue(label, row, "AptNo");

  label += "/n";

  labelLen = label.Length;

  label += AddFieldValue(label, row, "Address2");

  if (label.Length != labelLen)

  label += "/n";

  label += AddFieldValue(label, row, "City");

  label += AddFieldValue(label, row, "State");

  label += AddFieldValue(label, row, "Zip");

  Console.WriteLine(label);

  Console.WriteLine();

  }

  }

  private string AddFieldValue(string label, DataRow row,

  string fieldName)

  {

  if (! DBNull.Value.Equals(row[fieldName]))

  return (string) row[fieldName] + " ";

  else

  return String.Empty;

  }

  初学数据库编程我们可能会有一些对"空值"的疑问,比如通过编程新建的一个表中所有数据皆显示为,手动添加并删除文字后又变成了空白;一个字符串类型的字段,明明没有填值,却不等于"";用ADO.NET从数据库中取值,每遇到有的就出错……这需要我们正确认识。NET和SQL Server中几种不同的"空值".

  1、真正的空值,也就是"没有输入的值",可以出现在大多数类型的字段中(如果没有别的约束条件),SQL server中表示为null,显示为,手工在SQL server企业管理器中输入的方法是按Ctrl+0.它在。NET中对应System.DBNull.Value.在T-SQL命令中,判断一个值是不是空值,要用"is null"而不是"= null";处理空值有个ISNULL函数,它使用指定的值替换null.用ADO.NET从数据库得到的空值无法自动转化为空字符串或Nothing,须手动检测:如果得到System.DBNull.Value,则赋给数据对象Nothing或其它自定义的有意义的值。

  2、空字符串(零长度字符串),只出现在字符串类型(如nvarchar)的字段中,SQL server中表示为'',显示为空白,手工在SQL server企业管理器中输入时清空一个单元格即可。它在。NET中对应System.String.Empty,也就是我们常用的"".在T-SQL命令中处理空字符串和处理一般的字符串没什么区别。用ADO.NET从数据库得到的空字符串也和一般的字符串没什么区别。

  DBNull简介

  DBNull在DotNet是单独的一个类型 System.DBNull .它只有一个值 DBNull.Value .DBNull 直接继承 Object ,所以 DBNull 不是 string , 不是 int , 也不是 DateTime …

  但是为什么 DBNull 可以表示数据库中的字符串,数字,或日期呢?原因是DotNet储存这些数据的类(DataRow等)都是以 object 的形式来储存数据的。对于 DataRow , 它的 row[column] 返回的值永远不为 null , 要么就是具体的为column 的类型的值 . 要么就是 DBNull . 所以 row[column].ToString() 这个写法永远不会在ToString那里发生NullReferenceException.

  DBNull 实现了 IConvertible . 但是,除了 ToString 是正常的外,其他的ToXXX都会抛出不能转换的错误。

  在 IDbCommand(OleDbCommand,SqlCommand…) 的ExecuteScalar的返回值中,情况可以这样分析:

  select 1 这样返回的object是 1 select null 这样返回的是DBNull.Value select isnull(null,1) 返回的是 1 select top 0 id from table1 这样返回的值是null select isnull(id,0) from table1 where 1=0 返回的值是null

  这里 ExecuteScalar 的规则就是,返回第一列,第一行的数据。如果第一列第一行不为空,那么ExecuteScalar就直接对应的DotNet的值。如果有第一行,但是第一列为空,那么返回的是 DBNull .如果一行都没有,那么ExecuteScalar就返回null

  规则就是这样的。这里容易犯的一个错误是,把ExecuteScalar返回DBNull与null的情况混淆,例如:

  string username=cmd.ExecuteScalar()。ToString();

  除非你认为cmd执行后,肯定至少有一行数据,否则这里就会出错。

  又或者 select id from usertable where username=@name 这样的sql语句,如果找不到记录,那么ExecuteScalar则会返回null,所以千万不要

  int userid=Convert.ToInt32(cmd.ExecuteScalar());

  或者你会这样写 SQL 语句:select isnull(id,0) from usertable where username=@name

  但是 int userid=Convert.ToInt32(cmd.ExecuteScalar()); 依然会出错,因为上面的语句不成立时,仍然是不返回任何行。

  对于IDbDataParameter(OleDDbParameter,SqlParameter)的Value,如果为null,则代表该参数没有指定,或者是代表DEFAULT.如果为DBNull.Value,则代表SQL中的NULL

  所以,如果你要调用存储过程,里面有参数 @val nvarchar(20)="AABB" , 那么cmd.Parameters["@val"].Value=null 代表使用这个默认的 "AABB" 而cmd.Parameters["@val"].Value=DBNull.Value 代表使用NULL来传给 @val

  你可以用Convert.IsDBNull来判断一个值是否DBNull.注意Convert.IsDBNull(null)是false.

  补充:DBNull指的是数据库中的"null",而不是CLR中的"null".

  如很多初学者以为下面是一样的:

  cmd.Parameters["@payment_type"].Value = "";

  cmd.Parameters["@payment_type"].Value = System.DBNull.Value;

  ""表示的是空字符串,而System.DBNull.Value代表的是数据库中的NULL,既没有数据。就象老师说"0"不是没有一样