如何在SQL Server中将八个十六进制字节(16位)转换为十进制值?

时间:2019-09-09 18:48:40

标签: sql sql-server hex

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

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

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

didAppear()

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

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

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

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...

但这会导致:

  

信息8115,第16级,状态6,第17行
   算术溢出错误将varbinary转换为数值类型的数据。

1 个答案:

答案 0 :(得分:3)

如果为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分别存储有理数的有限子集,并且在任何一个系统中都可以精确表示许多数字。但是某些浮点值的十进制数并不完全匹配,反之亦然。