二进制类型加 1

Leo*_*res -1 sql t-sql sql-server

我有一个 cdc 表,其中有一个二进制序列列,我需要将表连接到二进制(10)类型的列上。我必须更改它的值,以便它与下一条记录匹配,这样我就可以返回数据集中的两行,因为更新将应用于此数据。

我需要更改0x0BB636D9239D01000000为,0x0BB636D9239D01000001以便我可以连接回表并获取数据。问题是我不能只添加+1,所以我可以添加到第一个二进制文件,使其像第二个二进制文件,这样我就可以获得下一个连续记录。

T N*_*T N 7

由于二进制值超过了 SQL Server 最大整数值(64 位的 BIGINT)的大小,因此您需要将该值除以并执行带进位的两步加法。

-- Split
DECLARE @UpperHalf BIGINT = SUBSTRING(@Binary, 1, 5)  -- Upper 5 bytes (40 bits)
DECLARE @LowerHalf BIGINT = SUBSTRING(@Binary, 6, 5)  -- Lower 5 bytes (40 bits)

-- Increment with carry
SET @LowerHalf += 1
SET @UpperHalf += RIGHT_SHIFT(@LowerHalf, 40) -- Carry
SET @LowerHalf &= 0xFFFFFFFFFF -- Trim

-- Combine
DECLARE @Result BINARY(10) =
     CONVERT(BINARY(5), @UpperHalf)
     + CONVERT(BINARY(5), @LowerHalf)
Run Code Online (Sandbox Code Playgroud)

这也可以包含在用户定义的函数中:

CREATE Function IncrementBinary10(@Binary BINARY(10))
RETURNS BINARY(10)
AS
BEGIN
    -- Split
    DECLARE @UpperHalf BIGINT = SUBSTRING(@Binary, 1, 5)  -- Upper 5 bytes (40 bits)
    DECLARE @LowerHalf BIGINT = SUBSTRING(@Binary, 6, 5)  -- Lower 5 bytes (40 bits)

    -- Increment with carry
    SET @LowerHalf += 1
    SET @UpperHalf += RIGHT_SHIFT(@LowerHalf, 40) -- Carry
    SET @LowerHalf &= 0xFFFFFFFFFF -- Trim

    -- Combine
    DECLARE @Result BINARY(10) =
         CONVERT(BINARY(5), @UpperHalf)
         + CONVERT(BINARY(5), @LowerHalf)
    RETURN @Result
END
Run Code Online (Sandbox Code Playgroud)

或者使用一系列CROSS APPLYs 内联实现:

CROSS APPLY (
    SELECT
        CAST(SUBSTRING(D.Binary, 1, 5) AS BIGINT) AS UpperHalf,
        CAST(SUBSTRING(D.Binary, 6, 5) AS BIGINT) AS LowerHalf
) S
CROSS APPLY (
    SELECT
        (S.LowerHalf + 1) & 0xFFFFFFFFFF AS LowerHalfIncremented,
        S.UpperHalf + RIGHT_SHIFT(S.LowerHalf + 1, 40) AS UpperHalfIncremented
) I
CROSS APPLY (
    SELECT
         CONVERT(BINARY(5), I.UpperHalfIncremented)
             + CONVERT(BINARY(5), I.LowerHalfIncremented)
             AS Result
) R
Run Code Online (Sandbox Code Playgroud)

结果示例:

二进制 函数结果 内联结果
0x0BB636D9239D01000000 0x0BB636D9239D01000001 0x0BB636D9239D01000001
0x00000000000000000000 0x00000000000000000001 0x00000000000000000001
0x00000000000000000001 0x00000000000000000002 0x00000000000000000002
0xFFFFFFFFFFFFFFFFFFFE 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0x00000000000000000000 0x00000000000000000000

请参阅此 db<>fiddle

上面使用了按位 RIGHT_SHIFT() 函数,该函数仅在 SQL Server 2022 及更高版本中可用。对于早期版本,可以使用整数除法 -/ 0x10000000000进行 40 位右移。(请注意,我们的分割值不使用所有 BIGINT 位,因此我们不需要担心负数,这不适用于简单的除法。)请参阅此 db<>fiddle