Considérer ce qui suit:
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
Production:
dt dt2 d
------------------ -------------------- --------
0x0000A13900000000 0x07000000000094360B 0x94360B
Maintenant, je comprends déjà de la documentation qui datetime
a une plage plus petite, et commence à partir de 1753-01-01, datetime2
et date
utilise 0001-01-01 comme date de début.
Ce que je ne comprends pas bien, est que datetime
semble être peu endian tout datetime2
et date
sont big-endian. Si tel est le cas, comment peuvent-ils même être correctement triés?
Considérez si je veux savoir combien de jours entiers sont représentés par un date
type. On pourrait penser que vous pourriez faire ceci:
declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)
Mais en raison de l'endianisme, vous obtenez 1966080 jours!
Pour obtenir le résultat correct de 30 jours, vous devez l'inverser:
select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
Ou bien sûr, vous pouvez le faire:
select datediff(d,'0001-01-01', @d)
Mais cela signifie en interne quelque part qu'il inverse les octets de toute façon.
Alors pourquoi ont-ils changé d'endianisme?
Je m'en soucie uniquement parce que je travaille sur un UDT personnalisé dans SQLCLR et l'ordre binaire des octets semble y avoir de l'importance, mais ces types intégrés semblent beaucoup plus flexibles. SQL Server a-t-il quelque chose de interne où chaque type peut fournir son propre algorithme de tri? Et si oui, existe-t-il un moyen de puiser dans cela pour mon UDT personnalisé?
Voir aussi, une question connexe (mais différente) sur StackOverflow.
la source
IComparable
? Vous ne devriez jamais avoir besoin de fouiller dans la représentation interne des types de données.IComparable
, mais il n'est utilisé que côté client. SQL Server l'ignore et désactive l'ordre des octets.Réponses:
SQL Server ne s'appuie pas sur l'ordre binaire pour ses «propres» types de données. Pour les types de données CLR, vous pouvez utiliser l'interface iComparable, mais comme @MattJohnson l'a mentionné, SQL Server l'ignore:
http://connect.microsoft.com/SQLServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts
Microsoft ne publie pas les détails sur la façon dont les différents types de données sont stockés et utilisés. Cependant, Books Online indique explicitement que vous ne pouvez pas compter sur un format binaire spécifique pour un type de données spécifique et que le format qu'ils utilisent peut changer à tout moment. C'est donc une bonne idée de stocker un INT comme cela et non comme VARBINARY, car vous ne pourrez peut-être plus lire vos données après le prochain SP.
Quant au tri: la majeure partie du cœur de SQL Server est écrite en C ++. Je suppose en interne qu'une méthode similaire à un iComparable est utilisée. Mais encore une fois, il n'y a pas de documentation accessible au public à ce sujet. Même si c'était le cas, vous ne seriez probablement pas en mesure de l'exploiter en raison des différences inhérentes entre .NET et C ++.
la source
int
comme champ de support de mon CLR UDT? Avez-vous un exemple de la façon de procéder? L'CREATE TYPE
instruction prendra unbase_type
ou un assemblage externe - mais pas les deux.