Учтите следующее:
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)
Но благодаря порядку байтов вы получаете 1966080 дней!
Чтобы получить правильный результат 30 дней, вы должны поменять его местами:
select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)
Или, конечно, вы можете сделать это:
select datediff(d,'0001-01-01', @d)
Но это означает, что внутренне где-то это все равно обращает байты.
Так почему же они поменяли порядок байтов?
Меня волнует только то, что я работаю над пользовательским UDT в SQLCLR, и двоичный порядок байтов, кажется, там имеет значение, но эти встроенные типы кажутся гораздо более гибкими. Есть ли в SQL Server что-то внутреннее, где каждый тип предоставляет собственный алгоритм сортировки? И если так, есть ли способ, которым я могу использовать это для своего пользовательского UDT?
См. Также связанный (но другой) вопрос о StackOverflow.
источник
IComparable
? Вам никогда не нужно копаться во внутреннем представлении типов данных.IComparable
, но он используется только на стороне клиента. SQL Server игнорирует его и отключает порядок байтов.Ответы:
SQL Server не использует двоичный порядок для своих «собственных» типов данных. Для типов данных CLR вы можете использовать интерфейс iComparable, но, как упомянул @MattJohnson, SQL Server игнорирует его:
http://connect.microsoft.com/SQLServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts
Microsoft не публикует подробности о том, как различные типы данных хранятся и работают с ними. Однако Books Online прямо заявляет, что вы не можете полагаться на конкретный двоичный формат для определенного типа данных и что формат, который они используют, может измениться в любое время. Поэтому хорошей идеей будет хранить INT как только это, а не как VARBINARY, потому что вы не сможете больше читать ваши данные после следующего SP.
Что касается сортировки: большая часть ядра SQL Server написана на C ++. Я предполагаю, что внутренне используется метод, похожий на iComparable. Но опять же, нет общедоступной документации об этом доступном. Даже если бы это было так, вы, вероятно, не смогли бы использовать его из-за внутренних различий между .NET и C ++.
источник
int
в качестве вспомогательного поля моего CLR UDT? У вас есть пример, как это сделать?CREATE TYPE
Заявление будет приниматьbase_type
или внешний монтаж - но не оба.