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, eu já entendem a partir da documentação que datetime
tem um alcance menor, e começa a partir de 1753/01/01, enquanto datetime2
e date
usar 0001-01-01 como sua data de início.
O que eu não entendo, porém, é que datetime
parece ser um pouco endian enquanto datetime2
e date
é um big end. Se for esse o caso, como eles podem ser classificados adequadamente?
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 à persistência, você recebe 1966080 dias!
Para obter o resultado correto de 30 dias, é necessário revertê-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á invertendo os bytes de qualquer maneira.
Então, por que eles trocaram endianness?
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 internos parecem muito mais flexíveis. O SQL Server tem algo interno onde cada tipo obtém para fornecer seu próprio algoritmo de classificação? E, em caso afirmativo, existe uma maneira de aproveitar isso para o meu UDT personalizado?
Consulte também uma pergunta relacionada (mas diferente) no StackOverflow.
fonte
IComparable
? Você não precisa se aprofundar na representação interna dos tipos de dados.IComparable
, mas ele é usado apenas no lado do cliente. O SQL Server o ignora e sai da ordem dos bytes.Respostas:
O SQL Server não depende da ordem binária para seus tipos de dados "próprios". Para tipos de dados CLR, você pode usar a interface iComparable, mas como o @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 afirma 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 idéia armazenar uma INT apenas isso e não como VARBINÁRIO, porque talvez você não consiga ler mais seus dados após o próximo SP.
Quanto à classificação: a maior parte do núcleo do SQL Server é escrita em C ++. Presumo internamente que um método semelhante a um iComparable seja usado. Porém, novamente, não há documentação publicamente acessível sobre isso disponível. Mesmo que fosse, você provavelmente não seria capaz de explorá-lo devido às diferenças inerentes entre o .NET e o C ++.
fonte
int
como o campo de apoio do meu CLR UDT? Você tem um exemplo de como fazer isso? ACREATE TYPE
declaração terábase_type
uma montagem, ou uma montagem externa - mas não ambas.