Understanding MS SQL Server Date Types

Mat*_*int 7 sql-server datatypes sql-clr datetime user-defined-type

Consider the following:

declare @dt datetime, @dt2 datetime2, @d date
set @dt  = '2013-01-01'
set @dt2 = '2013-01-01'
set @d   = '2013-01-01'

select convert(varbinary, @dt) as dt,
       convert(varbinary, @dt2) as dt2,
       convert(varbinary, @d) as d
Run Code Online (Sandbox Code Playgroud)

Output:

dt                    dt2                     d
------------------    --------------------    --------
0x0000A13900000000    0x07000000000094360B    0x94360B
Run Code Online (Sandbox Code Playgroud)

Now, I already understand from the documentation that datetime has a smaller range, and starts from 1753-01-01, while datetime2 and date use 0001-01-01 as their start date.

What I don't understand though, is that datetime appears to be little-endian while datetime2 and date are big-endian. If that's the case, how can they even be properly sortable?

Consider if I want to know how many integer days are represented by a date type. You would think you could do this:

declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)
Run Code Online (Sandbox Code Playgroud)

But due to the endianness, you get 1966080 days!

To get the correct result of 30 days, you have to reverse it:

select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
Run Code Online (Sandbox Code Playgroud)

Or, of course you can do this:

select datediff(d,'0001-01-01', @d)
Run Code Online (Sandbox Code Playgroud)

But that means internally somewhere it is reversing the bytes anyway.

So why did they switch endianness?

我只关心因为我正在 SQLCLR 中处理自定义 UDT,并且字节的二进制顺序在那里似乎很重要,但这些内置类型似乎更加灵活。SQL Server 是否有内部的东西,每种类型都可以提供它自己的排序算法?如果是这样,有没有办法为我的自定义 UDT 使用它?

另请参阅StackOverflow 上的一个相关(但不同)问题

Seb*_*ine 2

SQL Server 不依赖其“自己的”数据类型的二进制顺序。对于 CLR 数据类型,您可以使用 iComparable 接口,但正如 @MattJohnson 提到的,SQL Server 会忽略它:

http://connect.microsoft.com/SQLServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts


Microsoft 没有发布有关如何存储和使用不同数据类型的详细信息。然而,联机丛书明确指出,您不能依赖特定数据类型的特定二进制格式,并且它们使用的格式可能随时更改。因此,最好将 INT 存储为 INT 而不是 VARBINARY,因为在下一个 SP 之后您可能无法再读取数据。

至于排序:大部分SQL Server核心都是用C++编写的。我假设内部使用了类似于 iComparable 的方法。但同样,没有关于此的公开文档。即使是这样,您也可能无法利用它,因为 .NET 和 C++ 之间存在固有的差异。