【问题标题】:SQL split bigint into two intSQL 将 bigint 拆分为两个 int
【发布时间】:2015-10-13 16:35:14
【问题描述】:

为了与第 3 部分解决方案兼容,我需要将 bigint 字符串的两半的 unsigned int 等值存储在数据库的两个单独字段中。

我已经查看了这里的解决方案,它似乎运行良好,除了它经常返回负数的事实。我认为这是由于 SQL 期望它被签名的未签名数据的结果,但我推测那里......

SQL - safely downcast BIGINT to INT

DECLARE @BigintDataLimitIn BIGINT = 8589934590;
DECLARE @RightHalf INT, @LeftHalf INT;

WITH v AS (SELECT CAST(@BigintDataLimitIn AS varbinary) AS bin)
SELECT
  @LeftHalf = SUBSTRING(bin, 1, 4),
  @RightHalf  = SUBSTRING(bin, 5, 4)
FROM v;

SELECT @LeftHalf,  @RightHalf
----------------------------------------
(LeftHalf)  (RightHalf)
1           -2

所以我的问题是为什么右半边输出有时会返回不正确的负值,我该如何解决它才能始终正确?

当使用 .NET 执行此操作时,对于某些输入数字,我也看到了同样奇怪的结果。

Dim original As Int64 = 8589934590
Dim rightHalfUnSigned As UInt32 = CType(original And &H7FFFFFFF, UInt32)

Console.writeline(rightHalfUnSigned)
Output: 2147483646

我对这些函数的基础机制了解得不够透彻,无法知道为什么输入数字 8589934590 会发生这种情况,但对于 8589934595 来说却完美无缺。

【问题讨论】:

  • 向我们展示导致问题的数据样本,该样本的预期结果也会很好。
  • 正确输出:BIGINT = 8589934595 LeftHalf RightHalf RawBinary 2 3 0x0000000200000003 输出不正确:BIGINT = 8589934590 LeftHalf RightHalf RawBinary 2 -2 0x00000001FFFFFFFE

标签: sql-server


【解决方案1】:

SQL Server 将您的字节视为有符号整数并将其显示。二进制数据还是正确的。

大约一半的时间,代表数字的最低有效字节的那些字节将落在四字节有符号整数的负范围内。您会遇到相同的情况,将负值拆分:有时下半部分会是正值。

你可能会这样想。拆分为两个值后,您现在有了两个符号位(前导位),而不仅仅是您开始使用的那个。

这可能有助于取回您期望看到的无符号值:

cast(0x00000000 + cast(@RightHalf as binary(4)) as bigint)

可能更容易说如下,它将保留 bigint 类型:

@LeftHalf  = @BigintDataLimitIn / 4294967296
@RightHalf = @BigintDataLimitIn % 4294967296

【讨论】:

  • 那么如何将拆分值转换为正确的格式?
  • 你的目标是什么?看看他们是正确的?要出口?在报告上显示?
  • cast(0x00000000 + cast(@RightHalf as binary(4)) as bigint) 似乎在 SQL 方面起到了作用,你有没有机会在 VB.NET 代码上做同样的魔法?
  • 你能详细说明 bin % 4294967296 吗?我不明白你建议如何集成/实现它
  • 可能只选择其中之一:stackoverflow.com/questions/14708778/…
【解决方案2】:

完美、运行良好、代码行数比原始代码少。很棒的答案。

DECLARE @BigintDataLimitIn BIGINT = 8589934590;
DECLARE @RightHalf INT, @LeftHalf INT;

WITH v AS (SELECT CAST(@BigintDataLimitIn AS varbinary) AS bin)
SELECT
  @LeftHalf = SUBSTRING(bin, 1, 4)
FROM v;

SELECT @LeftHalf as LeftHalf,  @BigintDataLimitIn % 4294967296 as RightHalf
-----------------------------
LeftHalf    RightHalf
1           4294967294

【讨论】:

    猜你喜欢
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多