Considere o seguinte:
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
Resultado:
dt dt2 d
------------------ -------------------- --------
0x0000A13900000000 0x07000000000094360B 0x94360B
Agora, já entendi pela documentação que datetime
tem um intervalo menor e começa em 1753-01-01, enquanto datetime2
e date
usa 0001-01-01 como data de início.
O que eu não entendo, porém, é que datetime
parece ser little-endian while datetime2
e date
big-endian. Se for esse o caso, como eles podem ser adequadamente classificáveis?
Considere se eu quero saber quantos dias inteiros são representados por um date
tipo. Você pensaria que poderia fazer isso:
declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)
Mas devido ao endianness, você obtém 1966080 dias!
Para obter o resultado correto de 30 dias, você deve invertê-lo:
select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
Ou, claro, você pode fazer isso:
select datediff(d,'0001-01-01', @d)
Mas isso significa que internamente em algum lugar está revertendo os bytes de qualquer maneira.
Então, por que eles trocaram o endianness?
Eu só me importo porque estou trabalhando em um UDT personalizado no SQLCLR e a ordem binária dos bytes parece importar lá, mas esses tipos integrados parecem muito mais flexíveis. O SQL Server tem algo interno onde cada tipo consegue fornecer seu próprio algoritmo de classificação? E, em caso afirmativo, existe uma maneira de aproveitar isso para meu UDT personalizado?
Veja também uma questão relacionada (mas diferente) no StackOverflow.
O SQL Server não depende da ordem binária para seus "próprios" tipos de dados. Para tipos de dados CLR, você pode usar a interface iComparable, mas como @MattJohnson mencionou, o SQL Server a ignora:
http://connect.microsoft.com/SQLServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts
A Microsoft não publica os detalhes sobre como os diferentes tipos de dados são armazenados e trabalhados. No entanto, o Books Online declara explicitamente que você não pode confiar em um formato binário específico para um tipo de dados específico e que o formato que eles usam pode mudar a qualquer momento. Portanto, é uma boa ideia armazenar um INT apenas como isso e não como VARBINARY, porque você pode não conseguir mais ler seus dados após o próximo SP.
Quanto à classificação: a maior parte do núcleo do SQL Server é escrita em C++. Suponho que internamente seja usado um método semelhante a um iComparable. Mas, novamente, não há documentação acessível ao público sobre isso disponível. Mesmo que fosse, você provavelmente não seria capaz de explorá-lo devido às diferenças inerentes entre .NET e C++.