Leo*_*res -1 sql t-sql sql-server
我有一个 cdc 表,其中有一个二进制序列列,我需要将表连接到二进制(10)类型的列上。我必须更改它的值,以便它与下一条记录匹配,这样我就可以返回数据集中的两行,因为更新将应用于此数据。
我需要更改0x0BB636D9239D01000000为,0x0BB636D9239D01000001以便我可以连接回表并获取数据。问题是我不能只添加+1,所以我可以添加到第一个二进制文件,使其像第二个二进制文件,这样我就可以获得下一个连续记录。
由于二进制值超过了 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。