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

datetime vs datetimeoffset di SQL Server:Apa Bedanya?

Artikel ini menyoroti perbedaan utama antara waktu-tanggal dan datetimeoffset tipe data di SQL Server.

Kedua tipe data tersebut digunakan untuk menyimpan nilai tanggal dan waktu. Tetapi ada perbedaan yang signifikan antara keduanya.

Mungkin perbedaan yang paling jelas adalah datetimeoffset menyimpan offset zona waktu, sedangkan datetime tidak.

Perbedaan penting lainnya adalah datetimeoffset memungkinkan Anda untuk menentukan presisi (hingga 7 tempat desimal). Ini berarti datetimeoffset nilai dapat bervariasi dalam ukuran penyimpanannya, tergantung pada presisi yang digunakan.

waktu kencan type di sisi lain, memiliki ukuran dan presisi penyimpanan tetap.

Umumnya, Anda harus menghindari penggunaan datetime kecuali Anda memiliki alasan yang baik untuk menggunakannya (seperti mendukung sistem lama). Juga, datetime2 type lebih cocok daripada datetimeoffset , jadi sebaiknya Anda menggunakannya jika tidak memerlukan offset zona waktu.

Apa pun itu, inilah tabel yang membandingkan waktu-tanggal dan datetimeoffset :

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

* Ditambah 1 byte untuk menyimpan presisi dalam beberapa kasus. Lihat di bawah untuk info lebih lanjut.

8 byte
Akurasi 100 nanodetik Dibulatkan menjadi kelipatan .000, .003, atau .007 detik
Presisi pecahan detik yang ditentukan pengguna Ya Tidak
Rentang offset zona waktu -14:00 sampai +14:00 Tidak ada
Awas dan pelestarian zona waktu Ya Tidak
Mengingat musim panas Tidak Tidak

Contoh 1 – Perbandingan Dasar

Bagaimanapun, berikut adalah contoh cepat untuk menunjukkan perbedaan mendasar antara datetime dan datetimeoffset .

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

Hasil:

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

Di sini, saya menetapkan waktu tanggal variabel dengan nilai yang sama dengan datetimeoffset variabel. Hal ini menyebabkan nilai dikonversi ke datetime dan kemudian kita dapat menggunakan SELECT pernyataan untuk melihat nilai setiap variabel.

Dalam hal ini, datetimeoffset nilai termasuk offset zona waktu dan 7 tempat desimal. waktu kencan nilai di sisi lain, tidak termasuk offset zona waktu dan hanya memiliki 3 tempat desimal. Selanjutnya, angka pecahan ketiganya dibulatkan ke atas. Ini karena akurasinya selalu dibulatkan ke peningkatan .000, .003, atau .007 detik.

Contoh 2 – Menetapkan Nilai dari Literal String

Pada contoh sebelumnya, datetime 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.

Jika kami mencoba menetapkan nilai yang sama langsung ke datetime variabel kita mendapatkan kesalahan:

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

Hasil:

Msg 241, Level 16, State 1, Line 5
Conversion failed when converting date and/or time from character string.

Ini karena waktu tanggal tipe data tidak mendukung literal string dengan offset zona waktu. Selain itu, ini tidak mendukung literal string dengan lebih dari 3 tempat desimal.

Jadi, jika kita menghapus offset zona waktu, tetapi menyimpan semua pecahan detik, kita masih akan mendapatkan error:

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

Hasil:

Msg 241, Level 16, State 1, Line 5
Conversion failed when converting date and/or time from character string.

Untuk membuatnya berfungsi, kita perlu menetapkan nilai dengan tidak lebih dari 3 tempat desimal:

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

Hasil:

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

Apa pun itu, waktu kencan akan selalu memiliki nilai yang berbeda dengan datetimeoffset , karena tidak menyertakan offset zona waktu. Ini akan benar bahkan jika kita menggunakan presisi pecahan detik dan nilai pecahan detik yang sama.

Untuk menunjukkannya, inilah yang terjadi jika kita menetapkan nilai yang sama ke datetimeoffset :

DECLARE 
  @thedatetimeoffset datetimeoffset(3), 
  @thedatetime datetime;
SET @thedatetimeoffset = '2025-05-21 10:15:30.123';
SET @thedatetime = '2025-05-21 10:15:30.123';
SELECT 
  @thedatetimeoffset AS 'datetimeoffset',
  @thedatetime AS 'datetime';

Hasil:

+------------------------------------+-------------------------+
| datetimeoffset                     | datetime                |
|------------------------------------+-------------------------|
| 2025-05-21 10:15:30.1230000 +00:00 | 2025-05-21 10:15:30.123 |
+------------------------------------+-------------------------+

Dalam hal ini datetimeoffset menggunakan skala 3, yang memberikannya 3 tempat desimal (sama dengan datetime ). Ini dilakukan dengan menggunakan datetimeoffset(3) saat mendeklarasikan variabel.

Saya juga mengubah pecahan detik sehingga datetime tidak akan membulatkannya (sehingga kedua nilai memiliki bagian pecahan yang sama persis).

Apapun, datetimeoffset masih menambahkan offset zona waktu, setel ke nilai default +00:00.

Perhatikan bahwa sistem saya menampilkan angka nol di datetimeoffset bagian pecahan, tetapi nilainya hanya menggunakan 3 tempat desimal.

Contoh 3 – Ukuran Penyimpanan

waktu kencan tipe data menggunakan 8 byte.

offset datetime tipe data menggunakan 8, 9, atau 10 byte, tergantung pada presisinya.

Oleh karena itu, Anda tidak menghemat ukuran penyimpanan apa pun dengan menggunakan datetime .

Namun, jika Anda mengonversi datetimeoffset nilai ke konstanta biner, itu menambahkan 1 byte untuk menyimpan presisi.

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

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

Hasil

+------------------+------------+
| datetimeoffset   | datetime   |
|------------------+------------|
| 10               | 8          |
+------------------+------------+

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

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

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

Hasil

+------------------+------------+
| datetimeoffset   | datetime   |
|------------------+------------|
| 11               | 8          |
+------------------+------------+

Satu byte tambahan ditambahkan ke datetimeoffset nilai tetapi tidak ke datetime nilai. Ini karena datetimeoffset value membutuhkan byte tambahan untuk menyimpan presisi (karena presisi ditentukan pengguna). waktu kencan nilai di sisi lain memiliki presisi tetap, jadi presisi tidak perlu disimpan dengan nilai.

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 heksadesimal tersebut sebenarnya tidak menyertakan presisi saat menyimpan datetimeoffset nilai-nilai. Ini karena presisi termasuk dalam definisi kolom.

Untuk detail lebih lanjut tentang bagaimana tipe data ini disimpan dalam database, lihat Memahami Ukuran Penyimpanan 'datetimeoffset' di SQL Server.

Haruskah saya menggunakan 'datetime' atau 'datetimeoffset'?

Jika Anda perlu menyertakan offset zona waktu, maka Anda harus menggunakan datetimeoffset . Jika tidak, maka datetime mungkin cukup.

Namun, Microsoft menyarankan Anda menggunakan datetime2 untuk pekerjaan baru, karena memiliki banyak manfaat dibandingkan datetime .

Lihat datetime vs datetime2 untuk perbandingan tipe data ini.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cari Tahu apakah Tabel Dipartisi di SQL Server (T-SQL)

  2. Nonaktifkan Akun SA di SQL Server (Contoh T-SQL)

  3. SQL Server 2005 Bagaimana Membuat Batasan Unik?

  4. 3 Cara Mengembalikan Jumlah Baris di Setiap Partisi di SQL Server (T-SQL)

  5. Cara Drop Database dengan menggunakan TSQL dan GUI - Tutorial SQL Server / TSQL Bagian 25