【问题标题】:How to convert an eight hexadecimal bytes (16 digits) into decimal value in SQL Server?如何在 SQL Server 中将八个十六进制字节(16 位)转换为十进制值?
【发布时间】:2019-09-09 18:48:40
【问题描述】:

我们正在尝试将 SAS7BDAT 文件导入 SQL Server 数据库。 我们遇到的唯一问题是源十进制值被读取为浮点数。

使用名为 dsread 的命令行工具,我们找到了一个选项:

将 SAS7BDAT 文件中的 IEEE 浮点数值转换为其十进制表示可能会导致精度损失。要获得数据的无损表示,请使用 /l 标志:

sashelp> dsread /v /l prdsale
ACTUAL,PREDICT,COUNTRY,...
0x0000000000e88c40,0x0000000000908a40,CANADA...
0x0000000000388f40,0x0000000000907240,CANADA...
0x0000000000008340,0x0000000000708a40,CANADA...
0x0000000000108440,0x0000000000a88040,CANADA...
0x0000000000808440,0x0000000000308440,CANADA...
0x0000000000a08d40,0x0000000000607e40,CANADA...
...etc...

数字输出为 8 个十六进制字节(16 位),给出内部浮点表示,然后可用于在接收软件中重建完全相同的值。使用 /L 以大端顺序获取字节

运行一些测试,当我们使用 /L 标志时,我们可以看到十进制值 -1.457263 由值 0xcbbbea01f350f7bf 表示。我们一直想不通的是,如何将十六进制值转换为 SQL Server 十进制值?

我们尝试了许多变体,包括:

select CONVERT(decimal, convert(varbinary,'0xcbbbea01f350f7bf',1))

但这会导致:

消息 8115,第 16 级,状态 6,第 17 行
将 varbinary 转换为数字数据类型时出现算术溢出错误。

【问题讨论】:

  • 您需要从文件中提供的二进制表示中“计算”十进制值。为此,您需要了解如何在示例中读取十六进制值的逻辑,然后将其转换为适当的十进制值。如果你不能在纸上做到这一点,你就不能真正期望编写代码来做到这一点。您需要了解一件事的字节序。
  • 再试一次 - 如果您通过将数字转换为字符串来导出数字,可能会更容易导入
  • 感谢您的反馈,斯莫尔。我们也尝试将数据作为字符串导入。我们看到像 7.771561e-16 这样的指数值。我们已经获得了文件中两个数值的汇总数字,但我们无法完全匹配它们,因为这两列一直被解释为来自源的浮点值。显然,使用 /L 标志的数据输出是大端顺序。我会研究这意味着什么。

标签: sql sql-server hex


【解决方案1】:

如果0xcbbbea01f350f7bf = -1.457263,那么它看起来像是一个具有大端字节序的 IEEE 双精度浮点数。

所以反转字节(或者让它以小端方式导出)

0xcbbbea01f350f7bf -> 0xbff750f301eabbcb

然后将其转换为浮点数。您可以使用 CLR 或者您可以在此处尝试使用 TSQL 函数: Unpacking a binary string with TSQL

然后将其转换为小数。

select convert(decimal(36,17), dbo.[fnBinaryFloat2Float]( 0xbff750f301eabbcb ), 3)

你可以看到它保留了更接近浮点值的近似值

-1.45726299999999998

有没有办法重建没有差异的“完全相同的值”?

然后将数据保留为float(53),这与源中的数据类型完全相同,并且根本不将其转换为十进制。 decimalfloat 分别存储有理数的有限子集,并且许多数字都可以在任一系统中精确表示。但是有些浮点值在十进制中不完全匹配,反之亦然。

【讨论】:

  • 哇大卫布朗,谢谢!听起来有可能获得数据的无损表示,使用 /l 标志。数字输出为八个十六进制字节(16 位),给出内部浮点表示,然后可用于在接收软件中重建完全相同的值。有没有办法重建没有差异的“完全相同的值”?
猜你喜欢
  • 1970-01-01
  • 2019-01-23
  • 2011-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2013-09-12
相关资源
最近更新 更多