Hiểu các loại ngày của MS SQL Server


8

Hãy xem xét những điều sau đây:

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

Đầu ra:

dt                    dt2                     d
------------------    --------------------    --------
0x0000A13900000000    0x07000000000094360B    0x94360B

Bây giờ, tôi đã hiểu từ các tài liệudatetimecó một phạm vi nhỏ hơn, và bắt đầu từ 1753/01/01, trong khi datetime2datesử dụng 0001-01-01 như ngày bắt đầu của họ.

Mặc dù vậy, điều tôi không hiểu là datetimedường như là người cuối datetime2cùng và datelà người cuối cùng lớn. Nếu đó là trường hợp, làm thế nào họ thậm chí có thể được sắp xếp đúng?

Xem xét nếu tôi muốn biết có bao nhiêu ngày nguyên được biểu thị bằng một dateloại. Bạn sẽ nghĩ rằng bạn có thể làm điều này:

declare @d date
set @d = '0001-01-31'
select cast(convert(varbinary, @d) as int)

Nhưng do sự kết thúc, bạn nhận được 1966080 ngày!

Để có kết quả chính xác trong 30 ngày, bạn phải đảo ngược nó:

select cast(convert(varbinary,reverse(convert(varbinary, @d))) as int)

Hoặc, tất nhiên bạn có thể làm điều này:

select datediff(d,'0001-01-01', @d)

Nhưng điều đó có nghĩa là bên trong một nơi nào đó nó đang đảo ngược các byte.

Vậy tại sao họ chuyển đổi endianness?

Tôi chỉ quan tâm bởi vì tôi đang làm việc trên một UDT tùy chỉnh trong SQLCLR và thứ tự nhị phân của các byte dường như có vấn đề ở đó, nhưng các loại tích hợp này có vẻ linh hoạt hơn nhiều. SQL Server có nội dung nào đó trong đó mỗi loại sẽ cung cấp thuật toán sắp xếp riêng không? Và nếu vậy, có cách nào tôi có thể khai thác điều đó cho UDT tùy chỉnh của mình không?

Xem thêm, một câu hỏi liên quan (nhưng khác) trên StackOverflow.


Bạn đã thử thực hiện IComparable? Bạn không cần phải đi sâu vào biểu diễn bên trong của các loại dữ liệu.
Jon Seigel

Theo điều này (cuộn xuống "Thực hiện UDT với định dạng do người dùng xác định"), bạn có thể thực hiện IComparable, nhưng nó chỉ được sử dụng phía máy khách. SQL Server bỏ qua nó và tắt thứ tự byte.
Matt Johnson-Pint

Oh. Chà, thật khó chịu.
Jon Seigel

@PaulWhite - Điều đó thực sự hữu ích. Ít nhất đó là sự xác nhận về những gì tôi đang trải qua. Cảm ơn!
Matt Johnson-Pint

@PaulWhite - Phần anh ấy không đề cập đến trong bài viết đó là cách loại bỏ byte hàng đầu cho null. Tại sao một int cần phải được lưu trữ trong 5 byte?
Matt Johnson-Pint

Câu trả lời:


2

SQL Server không dựa vào thứ tự nhị phân cho các kiểu dữ liệu "riêng" của nó. Đối với kiểu dữ liệu CLR, bạn có thể sử dụng giao diện iComparable, nhưng như @MattJohnson đã đề cập, SQL Server bỏ qua nó:

http://connect.microsoft.com/QueryServer/feedback/details/252230/sqlclr-provide-the-ability-to-use-icomparable-or-a-similar-mechanism-for-udts


Microsoft không công bố các chi tiết về cách các kiểu dữ liệu khác nhau được lưu trữ và làm việc với. Tuy nhiên, Sách trực tuyến tuyên bố rõ ràng rằng bạn không thể dựa vào một định dạng nhị phân cụ thể cho một kiểu dữ liệu cụ thể và định dạng họ sử dụng có thể thay đổi bất cứ lúc nào. Vì vậy, đó là một ý tưởng tốt để lưu trữ một INT như vậy và không phải là VARBINARY, bởi vì bạn có thể không thể đọc dữ liệu của mình nữa sau SP tiếp theo.

Về phần sắp xếp: Hầu hết lõi SQL Server được viết bằng C ++. Tôi giả sử bên trong một phương thức tương tự như iComparable được sử dụng. Nhưng một lần nữa, không có tài liệu truy cập công khai về điều này có sẵn. Ngay cả nếu có, có lẽ bạn sẽ không thể khai thác nó vì sự khác biệt vốn có giữa .NET và C ++.


Số vấn đề khác được đề cập cũng có thông tin. Nhưng bạn có bất kỳ chi tiết liên quan đến cách các loại nội bộ làm điều đó?
Matt Johnson-Pint

@MattJohnson, xem cập nhật của tôi ở trên. Tôi sợ đó không phải là thứ bạn đang tìm kiếm ...
Sebastian Meine

Vì vậy, bạn có khuyên bạn nên sử dụng SQL intlàm trường sao lưu của CLR UDT của tôi không? Bạn có một ví dụ về cách làm điều đó? Các CREATE TYPEtuyên bố sẽ tham gia một base_type, hoặc một hội đồng bên ngoài - nhưng không phải cả hai.
Matt Johnson-Pint

Không, đó chỉ là một ví dụ. Điều tôi đang nói là bạn cần tìm cách tuần tự hóa UDT của mình để nó có thể được sắp xếp nhị phân, vì không có cách nào hiện tại để thực hiện giao diện iComparable (hoặc tương tự) và để SQL Server sử dụng nó.
Sebastian Meine
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.