Considera lo siguiente:
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
Salida:
dt dt2 d
------------------ -------------------- --------
0x0000A13900000000 0x07000000000094360B 0x94360B
Ahora, yo ya entiendo de la documentación que datetime
tiene un rango menor, y se inicia a partir de 01.01.1753, mientras que datetime2
y date
utilizo 0001-01-01 como su fecha de inicio.
Sin embargo, lo que no entiendo es que datetime
parece ser little endian datetime2
y date
big-endian. Si ese es el caso, ¿cómo pueden clasificarse correctamente?
Considere si quiero saber cuántos días enteros están representados por un date
tipo. Pensarías que podrías hacer esto:
declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)
Pero debido a la resistencia, ¡obtienes 1966080 días!
Para obtener el resultado correcto de 30 días, debe revertirlo:
select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
O, por supuesto, puedes hacer esto:
select datediff(d,'0001-01-01', @d)
Pero eso significa internamente en algún lugar que está invirtiendo los bytes de todos modos.
Entonces, ¿por qué cambiaron endianness?
Solo me importa porque estoy trabajando en un UDT personalizado en SQLCLR y el orden binario de los bytes parece importar allí, pero estos tipos incorporados parecen mucho más flexibles. ¿SQL Server tiene algo interno donde cada tipo puede proporcionar su propio algoritmo de clasificación? Y si es así, ¿hay alguna manera de aprovechar eso para mi UDT personalizado?
Consulte también una pregunta relacionada (pero diferente) sobre StackOverflow.
fuente
IComparable
? No debería necesitar profundizar en la representación interna de los tipos de datos, nunca.IComparable
, pero solo se usa del lado del cliente. SQL Server lo ignora y sale del orden de bytes.Respuestas:
SQL Server no se basa en el orden binario para sus tipos de datos "propios". Para los tipos de datos CLR, puede usar la interfaz iComparable, pero como mencionó @MattJohnson, SQL Server lo ignora:
http://connect.microsoft.com/SQLServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts
Microsoft no publica los detalles sobre cómo se almacenan y trabajan los diferentes tipos de datos. Sin embargo, Books Online declara explícitamente que no puede confiar en un formato binario específico para un tipo de datos específico y que el formato que usan puede cambiar en cualquier momento. Por lo tanto, es una buena idea almacenar un INT solo como eso y no como VARBINARIO, porque es posible que ya no pueda leer sus datos después del próximo SP.
En cuanto a la clasificación: la mayor parte del núcleo de SQL Server está escrito en C ++. Supongo que internamente se usa un método similar a un iComparable. Pero, de nuevo, no hay documentación de acceso público sobre esto disponible. Incluso si lo fuera, probablemente no podría explotarlo debido a las diferencias inherentes entre .NET y C ++.
fuente
int
como campo de respaldo de mi CLR UDT? ¿Tienes un ejemplo de cómo hacer eso? LaCREATE TYPE
declaración tomará unbase_type
ensamblaje externo o uno, pero no ambos.