以下を検討してください。
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
出力:
dt dt2 d
------------------ -------------------- --------
0x0000A13900000000 0x07000000000094360B 0x94360B
今、私はすでに ドキュメント からdatetime
の範囲が狭く、1753-01-01から始まることを理解していますが、datetime2
とdate
は開始日は0001-01-01。
しかし、私が理解していないのは、datetime
がリトルエンディアンであるように見える一方で、datetime2
およびdate
はビッグエンディアンであるということです。その場合、どのようにしてそれらを適切に並べ替えることができますか?
date
型で表される整数の日数を知りたいかどうか検討してください。あなたはこれを行うことができると思います:
declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)
しかし、エンディアンのため、1966600日になります!
30日間の正しい結果を得るには、それを元に戻す必要があります。
select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
または、もちろんこれを行うことができます:
select datediff(d,'0001-01-01', @d)
しかし、それは内部的にどこかでバイトを逆にしていることを意味します。
では、なぜエンディアンを切り替えたのでしょうか。
SQLCLRでカスタムUDTを処理していて、バイトのバイナリ順序が重要であるように見えるため、私は気にしていますが、これらの組み込み型ははるかに柔軟に見えます。 SQL Serverには、各タイプが独自のソートアルゴリズムを提供するための内部機能がありますか?もしそうなら、カスタムUDTのためにそれを利用できる方法はありますか?
StackOverflowの 関連する(ただし異なる)質問 も参照してください。
SQL Serverは、「独自の」データ型のバイナリ順序に依存しません。 CLRデータ型の場合、iComparableインターフェイスを使用できますが、@ MattJohnsonが述べたように、SQL Serverはそれを無視します。
Microsoftは、さまざまなデータ型がどのように格納され、処理されるかについての詳細を公開していません。ただし、Books Onlineでは、特定のデータ型について特定のバイナリ形式に依存することはできず、使用される形式はいつでも変更される可能性があると明示的に述べています。したがって、次のSPの後でデータを読み取ることができなくなる可能性があるため、VARBINARYとしてではなく、INTをそのまま格納することをお勧めします。
並べ替えについて:ほとんどのSQL ServerコアはC++で記述されています。内部的にはiComparableと同様のメソッドが使用されていると想定しています。しかし、繰り返しになりますが、これについて公開されているドキュメントはありません。たとえそうであっても、.NETとC++には固有の違いがあるため、おそらくそれを利用することはできません。