【问题标题】:bit data type returns -1位数据类型返回 -1
【发布时间】:2020-09-21 09:22:18
【问题描述】:

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

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

UPDATE myTable 
SET myColumn = 1

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

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

sqlCmd.CommandText = "SELECT myColumn FROM myTable"

sqlRdr = sqlCmd.ExecuteReader()

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

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

整数数据类型,可以取值 1、0 或 NULL。

字符串值 TRUE 和 FALSE 可以转换为位值:TRUE 转换为 1,FALSE 转换为 0。

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

【问题讨论】:

  • myColumn 的数据类型是什么?它在您的 VB.net 代码中是如何定义的?
  • @AaronBertrand 我相信 OP 在他的问题中已经说明了数据类型位。
  • @Mary 是 SQL Server 中表中的数据类型。我在询问 VB.net 代码中的 myColumn 变量。
  • 来自 MS Docs “从整数或浮点数到布尔值的所有转换都将非零值转换为真,零值转换为假。” docs.microsoft.com/en-us/dotnet/api/…
  • @AaronBertrand myColumn的数据类型在我遇到问题之前是Integer。然后我将其更改为数据类型Boolean 以按我的预期工作,但对后台发生的事情感到好奇,因此这篇文章。

标签: vb.net sql-server-2008 sqldatatypes


【解决方案1】:

当您获取bit 列的数据时,您实际上得到的是一个 32 位的数字,而不仅仅是一个位。在该 32 位数字中,每个位设置为 1 或每个位设置为 0。使用二进制补码转换为 Integer 时,值 11111111 11111111 11111111 11111111 为 -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。您不应该将从数据读取器获得的Object 引用分配给IntegerBoolean 类型的变量。您应该使用数据阅读器来获取实际类型的数据。如果你真的收到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()

【讨论】:

  • 我确实最终将 VB 代码中的 myColumn 更改为 Boolean 数据类型,因此在发表这篇文章之前我会得到预期的结果,但我想知道为什么我得到 -1。我认为您对二进制补码的引用为我指明了正确的方向,我将尝试消化一下。
【解决方案2】:

SQL Bit 类型映射到 .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 值。

【讨论】:

  • 没错,但我建议实际上应该做的是将myColumn 声明为Boolean 类型,然后使用sqlRdr.GetBoolean(0) 将值作为Boolean 获取。鉴于bit 列代表Boolean 数据,没有充分的理由不在VB 代码中使用Boolean
【解决方案3】:

True的数值为-1,False为0

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

【讨论】:

    猜你喜欢
    • 2014-08-29
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多