序言
我有启用了CDC的MSSQL 2016示例。我按Debezium kafka connector流更改。日志和主题中的连接器以000000aa:af9c3f2d:0f5e1
的形式引用Log Sequence Number (LSN)
。在MSSQL中,我有cdc.dbo_Entity_cdc_CT
这样的表,其中显示列__$start_lsn
、__$start_lsn
、__$end_lsn
,但它的类型为varbinary(10)
。
我会匹配价值观。
主要基于Day 11 of 31 Days of Disaster: Converting LSN Formats article中的信息,提示它应该在chainconvert to binary style 1-〉bigint中转换,我为此编写了帮助函数:www.example.comhttps://github.com/Hubbitus/sql/commit/4ccf96492f2aba9796ccaecb1b74e9ba53a45895#diff-e495aa591f98a29c28153735379ad6fd
它大部分工作。包含描述,甚至测试转换做正确的。
但有一个问题我现在解决不了。
8字节部分超出bigint
当我转换输入varbinary(16)
值时,我将其分为两部分:2字节和8字节长度,分别转换为bigint
,然后转换为varchar
,例如:
DECLARE @lsn VARBINARY(10) ...
-- Fill by \0 at left
SET @lsn = CONVERT(varbinary, REPLICATE(char(0), 10 - LEN(@lsn))) + @lsn
DECLARE @lsn_s varchar(max) = CONVERT(varchar, CONVERT(bigint, SUBSTRING(@lsn, 1, 2), 1)) + CONVERT(varchar, CONVERT(bigint, SUBSTRING(@lsn, 3, 8), 1))
它在大多数情况下有效(例如,对于测试表,我只看到4条记录有错误),例如,对于如下值:
DECLARE @lsn varbinary(10) = CONVERT(varbinary(10), '0x025D020F35B80001', 1)
您可以像这样检查:
SELECT dbo.__tmp_td_cdc_decode_check(CONVERT(varbinary(10), '0x025D020F35B80001', 1))
但是失败了,说:
DECLARE @lsn varbinary(10) = CONVERT(varbinary(10), '0x0043275D010200440020', 1)
SELECT dbo.__tmp_td_cdc_decode_check(@sql)
事实上,MSSQL have not unsigned datatypes.
主要问题是
- 我不知道如何在以下行中解决此问题**:
DECLARE @lsn_s varchar(max) = CONVERT(varchar, CONVERT(bigint, SUBSTRING(@lsn, 1, 2), 1)) + CONVERT(varchar, CONVERT(bigint, SUBSTRING(@lsn, 3, 8), 1))
- 在任何情况下,如何正确地将
varbinary(10)
转换为十进制数字形式的varchar
?**
- 在任何情况下,如何正确地将
什么我也不明白,有时我得到错误"数据截断"的转换,但有时它默默发生。请看:
DECLARE @lsn varbinary(10) = CONVERT(varbinary(10), '0x0043275D010200440020', 1) -- Bigint overflow
SELECT
dbo.__tmp_td_cdc_decode_check(@lsn) as ToCheck
,CONVERT(varchar, @lsn, 1) as orig_lsn_hex
,CONVERT(bigint, @lsn, 1) as orig_lsn_bigint -- In many cases it will lead overflow!
,dbo.__tmp_td_cdc_binary_decode_to_string(@lsn) as string
,dbo.__tmp_td_cdc_string_decode_to_binary_DECSTRING(dbo.__tmp_td_cdc_binary_decode_to_string(@lsn)) as decimal_string_reverse
输出:
┌─────────┬────────────────────────┬─────────────────────┬─────────────────────────┬────────────────────────┐
│ ToCheck │ orig_lsn_hex │ orig_lsn_bigint │ string │ decimal_string_reverse │
├─────────┼────────────────────────┼─────────────────────┼─────────────────────────┼────────────────────────┤
│ Error │ 0x0043275D010200440020 │ 2836424448419299360 │ 000012e6:2f707ba4:02580 │ 4838079590083609600 │
└─────────┴────────────────────────┴─────────────────────┴─────────────────────────┴────────────────────────┘
十六进制值0x0043275D010200440020
应该是1_238_768_277_386_959_257_632,而不是从CONVERT(bigint, @lsn, 1)
获得的2_836_424_448_419_299_360
P.S.也有趣和有用的材料:
1条答案
按热度按时间ozxc1zmp1#
如果你必须像使用“普通”十六进制值那样转换值,你需要更“聪明”一点。这是一个想法,使用计数: