位数据类型 returns -1

bit data type returns -1

我在 Visual Studio 2010 年开发 Web 应用程序。我正在使用 SQL Server 2008 写入和读取数据库 table。

我有一个数据库 table,myTable 有一个数据类型 bit 的列 myColumn。我在网络应用程序上写这个专栏是这样的:

UPDATE myTable 
SET myColumn = 1

这工作正常,并且使用 SQL Server Management Studio 我可以看到该列已更新为 TRUE,正如我所期望的那样。

在我的网络应用程序的另一部分中,我像这样查询 table:

sqlCmd.CommandText = "SELECT myColumn FROM myTable"

sqlRdr = sqlCmd.ExecuteReader()

While sqlRdr.Read
      myColumn = sqlRdr(0)
End While

当我 运行 这个查询时,myColumn 被设置为 -1。这是怎么发生的?根据Microsoft Documentation有点是

An integer data type that can take a value of 1, 0, or NULL.

The string values TRUE and FALSE can be converted to bit values: TRUE is converted to 1 and FALSE is converted to 0.

我不明白我是如何从这个查询中得到 myColumn = -1 的。

True的数值为-1,False的数值为0

Debug.Print(Val(True) & " " & Val(False))

SQL 位类型映射到 .Net 系统布尔类型 (True/False)。

你的代码,

myColumn = sqlRdr(0)

正在使用 VB 的隐式类型转换规则。推测 myColumn 是整数类型, sqlRdr(0) 返回的 Object 变量类型是布尔值。 VB 将 true 映射到值 -1,将 false 映射到值 0。

如果您使用 System.Convert.ToInt32 进行布尔值到整数的转换,则在转换布尔值真值时您将收到值一 (1)。

myColumn = System.Convert.ToInt32(sqlRdr(0))

请注意,如果您使用 VB 的首选 CInt 函数或 Ctype 函数,您也会收到 -1 值。

当您获取 bit 列的数据时,您实际上获取的是一个 32 位数字,而不仅仅是一个位。在那个 32 位数字中,要么每个位都设置为 1,要么每个位都设置为 0。使用二进制补码将值 11111111 11111111 11111111 11111111 转换为 Integer 时为 -1,因为第一位是符号位。

问题是您不应该在 VB 代码中使用 Integer。您唯一应该使用 1 或 0 来表示此数据的时间是 SQL 代码中的文字值。在您的 VB 代码中,您应该使用 Boolean 来表示此数据,因为这就是数据。 1 代表 True,0 代表 False,如果您在 SQL Server Management Studio 中查看数据,您会看到。

这意味着这里:

sqlCmd.CommandText = "SELECT myColumn FROM myTable"

sqlRdr = sqlCmd.ExecuteReader()

While sqlRdr.Read
      myColumn = sqlRdr(0)
End While

myColumn 变量的类型应为 Boolean。无论如何,该代码根本不应该编译,因为它需要 Option Strict Off 并且你应该几乎总是有 Option Strict On。您不应将从数据 reader 中获得的 Object 引用分配给 IntegerBoolean 类型的变量。您应该使用数据 reader 来获取数据的实际类型。如果你真的得到 Integer:

myColumn = sqlRdr.GetInt32(0)

但是,你会正确地使用 Boolean:

myColumn = sqlRdr.GetBoolean(0)

如果您想保存数据,那么您通常会使用参数,例如

sqlCmd.CommandText = "UPDATE myTable SET myColumn = @myColumn"
sqlCmd.Parameters.Add("@myColumn", SqlDbType.Bit).Value = True
sqlCmd.ExecuteNonQuery()