Change Data Capture if enabled on Database & Tables stores pre and post modification data in separate set of tables. In our project we were using this data regenerate Insert, Update and Delete Statement.
If there are 10 columns and if 2 columns are updated, CDC maintains bitmap for indicating all columns that are modified. To find out exact column we were doing & (And) operation. And below issue was found during testing.
Decimal | Binary | Hex | Length (in Bytes) |
1 | 00000001 | 0x1 | 1 Byte |
2 | 00000010 | 0x2 | 1 Byte |
4 | 00000100 | 0x4 | 1 Byte |
8 | 00001000 | 0x8 | 1 Byte |
16 | 00010000 | 0x10 | 1 Byte |
32 | 00100000 | 0x20 | 1 Byte |
64 | 01000000 | 0x40 | 1 Byte |
128 | 10000000 | 0x80 | 1 Byte |
SelectLEN(1),LEN(2),LEN(4),LEN(8),LEN(16),LEN(32),LEN(64),LEN(128)
What would be output of such query? If you thought it would be 1 (since they are all 1 byte) it is wrong.
Instead treat them as Character data type and SQL would give result as
1 for all single digit numbers (1,2,4,8)
2 for all double digit numbers (16,32)
3 for all triple digit numbers (128)
Now it gets more interesting..
SelectLEN(0x1), LEN(0x2), LEN(0x4), LEN(0x8), LEN(0x10), LEN(0x20), LEN(0x40) , LEN(0x80)
- LEN(0x1) - 1 Byte
- LEN(0x2) - 1 Byte
- LEN(0x4) - 1 Byte
- LEN(0x8) - 1 Byte
- LEN(0x10) -1 Byte
- LEN(0x20) –0 Byte
- LEN(0x40) – 1 Byte
- LEN(0x80) – 1 Byte
Now see above, Len(0x20) is 0 (Zero) bytes?? What about LEN(0X200) – 2 Bytes, this seems correct.
It happens only with LEN(0X20) that is always 0.
What could be the reason? Try this
Select CHAR(0x1) as [0x1], CHAR(0x2) as [0x2], CHAR(0x4) as [0x4],
CHAR(0x8) as [0x8], CHAR(0x10) as [0x10],CHAR(0x20) as [0x20],
CHAR(0x40) as [0x40], CHAR(0x80) as [0x10]
Notice above 0x20 there is nothing implying 0x20 is “ “ (space).
May be what is happing is when we say Len(0x20), since it is space SQL Server truncates (trailing spaces) and finds out length. So instead of 1 we get 0.
From SelectLEN(1),LEN(2),LEN(4),LEN(8),LEN(16),LEN(32),LEN(64),LEN(128) we see that even though data type passed is integer, SQL treats them as Character data and finds length.
I think length is more biased towards character data even though it supports other data types as well.
Well what is workaround, Workaround is to use DataLength instead of Len() function
SelectDATALENGTH(0x1), DATALENGTH(0x2), DATALENGTH(0x4), DATALENGTH(0x8), DATALENGTH(0x10), DATALENGTH(0x20), DATALENGTH(0x40) , DATALENGTH(0x80)
Hope this is useful tip
Until next time, keep in touch.
-Guru