Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

datetime2 vs datetimeoffset di SQL Server:Apa Perbedaannya?

Artikel ini membahas perbedaan utama antara datetime2 dan datetimeoffset tipe data di SQL Server.

Kedua tipe data tersebut digunakan untuk menyimpan nilai tanggal dan waktu. Keduanya sangat mirip, tetapi dengan satu perbedaan utama; offset datetime menyimpan offset zona waktu.

Ini juga menghasilkan datetimeoffset menggunakan lebih banyak ruang penyimpanan daripada datetime2 , jadi Anda hanya akan menggunakan datetimeoffset jika Anda membutuhkan offset zona waktu.

Berikut tabel yang menjelaskan perbedaan utama antara kedua jenis ini.

Fitur datetimeoffset datetime2
Sesuai dengan SQL (ANSI &ISO 8601) Ya Ya
Rentang Tanggal 0001-01-01 hingga 9999-12-31 0001-01-01 hingga 9999-12-31
Rentang Waktu 00:00:00 sampai 23:59:59.9999999 00:00:00 sampai 23:59:59.9999999
Panjang Karakter Minimum 26 posisi
maksimum 34
Minimum 19 posisi
maksimum 27
Ukuran Penyimpanan 8 hingga 10 byte, tergantung pada presisi*

* Ditambah 1 byte untuk menyimpan presisi

6 hingga 8 byte, tergantung pada presisi*

* Ditambah 1 byte untuk menyimpan presisi

Akurasi 100 nanodetik 100 nanodetik
Presisi kedua pecahan Ya Ya
Presisi pecahan detik yang ditentukan pengguna Ya Ya
Rentang offset zona waktu -14:00 sampai +14:00 Tidak ada
Awas dan pelestarian zona waktu Ya Tidak
Mengingat musim panas Tidak Tidak

Haruskah saya menggunakan 'datetime2' atau 'datetimeoffset'?

Ini tergantung pada apakah Anda perlu menyertakan offset zona waktu atau tidak.

Jika Anda perlu menyertakan offset zona waktu, maka Anda harus menggunakan datetimeoffset .

Jika tidak, gunakan datetime2 , karena Anda akan menghemat ruang penyimpanan dan menghilangkan potensi masalah apa pun dengan memiliki offset zona waktu (yang berpotensi salah) dalam data Anda.

Contoh 1 – Perbandingan Dasar

Berikut adalah contoh cepat untuk menunjukkan perbedaan mendasar antara datetime2 dan 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';

Hasil:

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

Di sini, saya menetapkan datetime2 variabel dengan nilai yang sama dengan datetimeoffset variabel. Ini menyebabkan nilai dikonversi menjadi datetime2 dan kemudian kita dapat menggunakan SELECT pernyataan untuk melihat nilai setiap variabel.

Kedua variabel menggunakan skala 7, yang berarti mereka memiliki 7 tempat desimal.

Jadi dalam hal ini, satu-satunya perbedaan antara keduanya adalah datetimeoffset nilai mencakup offset zona waktu dan datetime2 nilainya tidak.

Contoh 2 – Mengubah Presisi

Kedua jenis memungkinkan Anda untuk menentukan presisi (dengan menggunakan skala antara 0 dan 7). Oleh karena itu, dimungkinkan untuk menyetel datetime2 nilai ke presisi yang lebih rendah daripada datetimeoffset nilai (dan sebaliknya).

Contoh:

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';

Hasil:

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

Di sini saya mengatur datetime2 nilai ke skala 3, yang berarti berakhir dengan 3 tempat desimal, bukan 7. Dalam hal ini, pecahan detiknya dibulatkan ke atas (karena angka pecahan berikutnya adalah 5 atau lebih tinggi).

Jadi kita dapat melihat bahwa mungkin untuk mendapatkan nilai tanggal/waktu yang berbeda bergantung pada pecahan detik yang kita tetapkan ke datetime2 . Ini juga berfungsi sebaliknya (mis. jika kita mengonversi dari datetime2(7) ke datetimeoffset(3) ).

Namun, jika kita mengurangi bagian pecahan, tidak ada pembulatan yang dilakukan:

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';

Hasil:

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

Contoh 3 – Menetapkan Nilai dari Literal String

Pada contoh sebelumnya, datetime2 nilai ditetapkan dengan menyetelnya ke nilai yang sama dengan datetimeoffset nilai. Ketika kami melakukannya, SQL Server melakukan konversi implisit agar data "sesuai" dengan tipe data baru.

Kami juga dapat menetapkan nilai yang sama secara langsung ke datetime2 variabel (meskipun dokumentasi resmi tidak secara eksplisit menyatakan bahwa ia menerima string literal dengan zona waktu offset):

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';

Hasil:

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

Contoh 4 – Ukuran Penyimpanan

datetime2 tipe data menggunakan penyimpanan dua byte lebih sedikit daripada datetimeoffset untuk presisi tertentu.

datetime2 dapat berupa 6, 7, atau 8 byte, tergantung pada presisinya.

offset datetime dapat berupa 8, 9, atau 10 byte, tergantung pada presisinya.

Microsoft menyatakan bahwa datetime2 type juga menggunakan 1 byte tambahan untuk menyimpan presisinya, dalam hal ini akan menggunakan setidaknya 3 byte lebih dari smalldatetime .

Ini juga berlaku untuk datetimeoffset (meskipun tidak secara eksplisit dinyatakan dalam dokumentasi Microsoft).

Namun, itu tergantung pada apakah kita menyimpannya dalam tabel atau variabel, dan apakah kita mengonversinya menjadi konstanta biner atau tidak.

Inilah yang terjadi jika kita menggunakan DATALENGTH() fungsi untuk mengembalikan jumlah byte yang digunakan untuk setiap nilai kita:

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';

Hasil

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

Seperti yang diharapkan, 10 byte untuk datetimeoffset dan 8 byte untuk datetime2 .

Tetapi jika kita mengonversinya menjadi varbinary , kita mendapatkan yang berikut:

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';

Hasil

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

Satu byte tambahan ditambahkan ke setiap nilai untuk menyimpan presisi.

Banyak pengembang berasumsi bahwa mengonversi ke varbinary mewakili bagaimana SQL Server benar-benar menyimpan nilai tanggal dan waktu. Namun ini hanya sebagian benar.

Meskipun benar bahwa SQL Server menyimpan nilai tanggal dan waktunya dalam heksadesimal, nilai hex tersebut sebenarnya tidak menyertakan presisi. Ini karena presisi termasuk dalam definisi kolom. Tetapi ketika kita mengonversi ke varbinary seperti yang kita lakukan pada contoh sebelumnya, presisi ditambahkan, dan ini menambahkan byte tambahan.

Untuk detail lebih lanjut tentang bagaimana tipe data ini disimpan dalam konteks yang berbeda, lihat artikel berikut:

  • Memahami Ukuran Penyimpanan 'datetimeoffset' di SQL Server
  • Memahami Ukuran Penyimpanan 'datetime2' di 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. Lewati variabel ke pemicu

  2. Cara Memilih Setiap Baris Di Mana Nilai Kolom TIDAK Berbeda

  3. SQL Server Ketersediaan tinggi:Instal contoh cluster failover SQL Server Bagian 2

  4. Cara mengembalikan hanya Tanggal dari tipe data DateTime SQL Server

  5. Gabungkan banyak baris menjadi satu string teks dengan pengelompokan