Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

datetime2 so với datetimeoffset trong SQL Server:Sự khác biệt là gì?

Bài viết này xem xét những điểm khác biệt chính giữa datetime2 datetimeoffset kiểu dữ liệu trong SQL Server.

Cả hai kiểu dữ liệu đều được sử dụng để lưu trữ các giá trị ngày và giờ. Cả hai đều rất giống nhau, nhưng có một điểm khác biệt chính; datetimeoffset lưu trữ độ lệch múi giờ.

Điều này cũng dẫn đến datetimeoffset sử dụng nhiều dung lượng bộ nhớ hơn datetime2 , vì vậy bạn sẽ chỉ sử dụng datetimeoffset nếu bạn cần chênh lệch múi giờ.

Dưới đây là bảng phác thảo sự khác biệt chính giữa hai loại này.

Tính năng datetimeoffset datetime2
Tuân thủ SQL (ANSI &ISO 8601)
Phạm vi ngày 0001-01-01 đến 9999-12-31 0001-01-01 đến 9999-12-31
Phạm vi thời gian 00:00:00 đến 23:59:59.9999999 00:00:00 đến 23:59:59.9999999
Độ dài ký tự tối thiểu 26 vị trí
tối đa 34 vị trí
tối thiểu 19 vị trí
tối đa 27 vị trí
Kích thước bộ nhớ 8 đến 10 byte, tùy thuộc vào độ chính xác *

* Thêm 1 byte để lưu trữ độ chính xác

6 đến 8 byte, tùy thuộc vào độ chính xác *

* Thêm 1 byte để lưu trữ độ chính xác

Độ chính xác 100 nano giây 100 nano giây
Độ chính xác phân số giây
Độ chính xác phân số giây do người dùng xác định
Khoảng chênh lệch múi giờ -14:00 đến +14:00 Không có
Nhận biết và bảo toàn độ lệch múi giờ Không
Nhận biết tiết kiệm ánh sáng ban ngày Không Không

Tôi nên sử dụng "datetime2" hay "datetimeoffset"?

Điều này phụ thuộc vào việc bạn có cần bao gồm chênh lệch múi giờ hay không.

Nếu bạn cần bao gồm chênh lệch múi giờ, thì bạn sẽ cần sử dụng datetimeoffset .

Nếu không, hãy sử dụng datetime2 , vì bạn sẽ tiết kiệm được dung lượng bộ nhớ và loại bỏ mọi vấn đề tiềm ẩn về việc chênh lệch múi giờ (có thể sai) trong dữ liệu của mình.

Ví dụ 1 - So sánh Cơ bản

Dưới đây là một ví dụ nhanh để chứng minh sự khác biệt cơ bản giữa datetime2 datetimeoffset .

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(7);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
SET @thedatetime2 = @thedatetimeoffset;
SELECT 
  @thedatetimeoffset AS 'datetimeoffset',
  @thedatetime2 AS 'datetime2';

Kết quả:

+------------------------------------+-----------------------------+
| datetimeoffset                     | datetime2                   |
|------------------------------------+-----------------------------|
| 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 |
+------------------------------------+-----------------------------+

Ở đây, tôi đặt datetime2 biến thành cùng một giá trị với datetimeoffset Biến đổi. Điều này khiến giá trị được chuyển đổi thành datetime2 và sau đó chúng ta có thể sử dụng SELECT để xem giá trị của mỗi biến.

Cả hai biến đều sử dụng thang điểm 7, có nghĩa là chúng có 7 chữ số thập phân.

Vì vậy, trong trường hợp này, sự khác biệt duy nhất giữa cả hai là bộ ngày giờ giá trị bao gồm chênh lệch múi giờ và datetime2 giá trị không.

Ví dụ 2 - Thay đổi Độ chính xác

Cả hai loại đều cho phép bạn chỉ định độ chính xác (bằng cách sử dụng thang điểm từ 0 đến 7). Do đó, có thể đặt datetime2 giá trị có độ chính xác thấp hơn datetimeoffset giá trị (và ngược lại).

Ví dụ:

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(3);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
SET @thedatetime2 = @thedatetimeoffset;
SELECT 
  @thedatetimeoffset AS 'datetimeoffset',
  @thedatetime2 AS 'datetime2';

Kết quả:

+------------------------------------+-------------------------+
| datetimeoffset                     | datetime2               |
|------------------------------------+-------------------------|
| 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.556 |
+------------------------------------+-------------------------+

Ở đây tôi đặt datetime2 giá trị thành thang 3, có nghĩa là nó kết thúc bằng 3 chữ số thập phân thay vì 7. Trong trường hợp này, giây phân số của nó được làm tròn lên (vì chữ số phân số tiếp theo là 5 hoặc cao hơn).

Vì vậy, chúng tôi có thể thấy rằng có thể nhận được một giá trị ngày / giờ khác tùy thuộc vào số giây phân đoạn mà chúng tôi chỉ định cho datetime2 . Điều này cũng hoạt động theo cách khác (ví dụ:nếu chúng tôi chuyển đổi từ datetime2 (7) đến datetimeoffset (3) ).

Tuy nhiên, nếu chúng ta giảm phần phân số, thì không có phép làm tròn nào được thực hiện:

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(3);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5554444 +07:30';
SET @thedatetime2 = @thedatetimeoffset;
SELECT 
  @thedatetimeoffset AS 'datetimeoffset',
  @thedatetime2 AS 'datetime2';

Kết quả:

+------------------------------------+-------------------------+
| datetimeoffset                     | datetime2               |
|------------------------------------+-------------------------|
| 2025-05-21 10:15:30.5554444 +07:30 | 2025-05-21 10:15:30.555 |
+------------------------------------+-------------------------+

Ví dụ 3 - Đặt giá trị từ chữ viết chuỗi

Trong các ví dụ trước, datetime2 giá trị đã được chỉ định bằng cách đặt nó thành giá trị giống như bộ datetimeoffs giá trị. Khi chúng tôi làm điều đó, SQL Server thực hiện một chuyển đổi ngầm định để dữ liệu “khớp” với kiểu dữ liệu mới.

Chúng tôi cũng có thể chỉ định cùng một giá trị trực tiếp cho datetime2 biến (mặc dù tài liệu chính thức không tuyên bố rõ ràng rằng nó chấp nhận một chuỗi ký tự với độ lệch múi giờ):

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(7);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
SET @thedatetime2 = '2025-05-21 10:15:30.5555555 +07:30';
SELECT 
  @thedatetimeoffset AS 'datetimeoffset',
  @thedatetime2 AS 'datetime2';

Kết quả:

+------------------------------------+-----------------------------+
| datetimeoffset                     | datetime2                   |
|------------------------------------+-----------------------------|
| 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 |
+------------------------------------+-----------------------------+

Ví dụ 4 - Kích thước bộ nhớ

datetime2 loại dữ liệu sử dụng ít bộ nhớ hơn hai byte so với datetimeoffset cho bất kỳ độ chính xác nhất định nào.

datetime2 có thể là 6, 7 hoặc 8 byte, tùy thuộc vào độ chính xác của nó.

datetimeoffset có thể là 8, 9 hoặc 10 byte, tùy thuộc vào độ chính xác của nó.

Microsoft tuyên bố rằng datetime2 type cũng sử dụng thêm 1 byte để lưu trữ độ chính xác của nó. Trong trường hợp đó, type sẽ sử dụng ít hơn 3 byte so với smalldatetime .

Điều này cũng áp dụng cho datetimeoffset (mặc dù nó không được nêu rõ ràng trong tài liệu của Microsoft).

Tuy nhiên, điều đó phụ thuộc vào việc chúng ta đang lưu trữ nó trong bảng hay trong một biến và liệu chúng ta có đang chuyển đổi nó thành một hằng số nhị phân hay không.

Đây là điều sẽ xảy ra nếu chúng tôi sử dụng DATALENGTH() hàm để trả về số byte được sử dụng cho mỗi giá trị của chúng ta:

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(7);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
SET @thedatetime2 = @thedatetimeoffset;
SELECT 
  DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset',
  DATALENGTH(@thedatetime2) AS 'datetime2';

Kết quả

+------------------+-------------+
| datetimeoffset   | datetime2   |
|------------------+-------------|
| 10               | 8           |
+------------------+-------------+

Như mong đợi, 10 byte cho datetimeoffset và 8 byte cho datetime2 .

Nhưng nếu chúng tôi chuyển đổi chúng thành varbinary , chúng tôi nhận được những điều sau:

DECLARE 
  @thedatetimeoffset datetimeoffset(7), 
  @thedatetime2 datetime2(7);
SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
SET @thedatetime2 = @thedatetimeoffset;
SELECT 
  DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset',
  DATALENGTH(CAST(@thedatetime2 AS varbinary(16))) AS 'datetime2';

Kết quả

+------------------+-------------+
| datetimeoffset   | datetime2   |
|------------------+-------------|
| 11               | 9           |
+------------------+-------------+

Một byte phụ được thêm vào mỗi giá trị để lưu trữ độ chính xác.

Nhiều nhà phát triển giả định rằng chuyển đổi thành varbinary đại diện cho cách SQL Server thực sự lưu trữ các giá trị ngày và giờ. Tuy nhiên điều này chỉ đúng một phần.

Mặc dù đúng là SQL Server lưu trữ các giá trị ngày và giờ của nó ở dạng thập lục phân, nhưng giá trị hex đó không thực sự bao gồm độ chính xác. Điều này là do độ chính xác được bao gồm trong định nghĩa cột. Nhưng khi chúng tôi chuyển đổi thành varbinary như chúng ta đã làm trong ví dụ trước, độ chính xác được thêm vào trước và điều này thêm một byte bổ sung.

Để biết thêm chi tiết về cách các loại dữ liệu này được lưu trữ trong các ngữ cảnh khác nhau, hãy xem các bài viết sau:

  • Hiểu Kích thước Bộ nhớ 'datetimeoffset' trong SQL Server
  • Hiểu Kích thước Bộ nhớ ‘datetime2’ trong SQL Server

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Liệt kê tất cả các cột không thể xóa trong cơ sở dữ liệu máy chủ SQL

  2. Cài đặt SQL Server 2016

  3. Toán tử T-SQL XOR

  4. 2 cách tạo bảng nếu nó không tồn tại trong SQL Server

  5. INFORMATION_SCHEMA so với sysobjects