Artikel ini membahas perbedaan utama antara datetime2 dan waktu kecil tipe data di SQL Server.
Kedua tipe data tersebut digunakan untuk menyimpan nilai tanggal dan waktu, namun ada beberapa perbedaan penting di antara keduanya. Dalam kebanyakan kasus, Anda lebih baik menggunakan datetime2 (Microsoft juga merekomendasikan ini), namun mungkin ada beberapa skenario di mana Anda perlu menggunakan smalldatetime .
Berikut tabel yang menjelaskan perbedaan utama antara kedua jenis ini.
Fitur | waktu kecil | datetime2 |
---|---|---|
Sesuai dengan SQL (ANSI &ISO 8601) | Tidak | Ya |
Rentang Tanggal | 1900-01-01 hingga 2079-06-06 | 0001-01-01 hingga 9999-12-31 |
Rentang Waktu | 00:00:00 sampai 23:59:59 | 00:00:00 sampai 23:59:59.9999999 |
Panjang Karakter | Maksimum 19 posisi | Minimum 19 posisi maksimum 27 |
Ukuran Penyimpanan | 4 byte, diperbaiki | 6 hingga 8 byte, tergantung pada presisi* * Ditambah 1 byte untuk menyimpan presisi |
Akurasi | Satu menit | 100 nanodetik |
Presisi kedua pecahan | Tidak | Ya |
Presisi pecahan detik yang ditentukan pengguna | Tidak | Ya |
Offset Zona Waktu | Tidak ada | Tidak ada |
Awas dan pelestarian zona waktu | Tidak | Tidak |
Mengingat musim panas | Tidak | Tidak |
Keuntungan dari 'datetime2'
Seperti yang terlihat pada tabel di atas, datetime2 type memiliki banyak keunggulan dibandingkan smalldatetime , termasuk:
- rentang tanggal yang lebih besar
- presisi detik pecahan
- presisi yang ditentukan pengguna opsional
- akurasi lebih tinggi
- sejajar dengan standar SQL (ANSI &ISO 8601)
* Dalam beberapa kasus datetime2 value menggunakan byte ekstra untuk menyimpan presisi, namun saat disimpan dalam database, presisi disertakan dalam definisi kolom, sehingga nilai tersimpan yang sebenarnya tidak memerlukan byte tambahan.
Haruskah saya menggunakan 'datetime' atau 'smalldatetime'?
Microsoft merekomendasikan datetime2 untuk pekerjaan baru (dan untuk alasan yang sama seperti yang disebutkan di atas).
Oleh karena itu, Anda harus menggunakan datetime2 , kecuali Anda memiliki alasan khusus untuk tidak melakukannya (seperti bekerja dengan sistem lama).
Contoh 1 – Perbandingan Dasar
Berikut adalah contoh cepat untuk menunjukkan perbedaan mendasar antara datetime2 dan waktu kecil .
DECLARE @thedatetime2 datetime2(7), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.5555555'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
Hasil:
+-----------------------------+---------------------+ | datetime2 | smalldatetime | |-----------------------------+---------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:16:00 | +-----------------------------+---------------------+
Di sini, saya menyetel smalldatetime variabel dengan nilai yang sama dengan datetime2 variabel. Ini menyebabkan nilai dikonversi ke smalldatetime dan kemudian kita dapat menggunakan SELECT
pernyataan untuk melihat nilai setiap variabel.
Dalam hal ini, datetime2 variabel menggunakan skala 7, yang berarti memiliki 7 tempat desimal. waktu kecil nilai di sisi lain, tidak memiliki apa pun tempat desimal. Selanjutnya, detiknya disetel ke nol, dan menitnya dibulatkan.
Hal ini diharapkan, karena dokumentasi resmi Microsoft menyatakan bahwa smalldatetime
waktu berdasarkan 24 jam sehari, dengan detik selalu nol (:00) dan tanpa pecahan detik
.
Jadi kita dapat melihat bahwa datetime2 type memberikan nilai tanggal/waktu yang jauh lebih tepat dan akurat.
Tentu saja, Anda mungkin tidak membutuhkan semua detik pecahan itu. Salah satu hal baik tentang datetime2 adalah Anda dapat menentukan berapa banyak (jika ada) detik pecahan yang Anda inginkan.
Contoh 2 – Menggunakan Lebih Sedikit Tempat Desimal
Dalam contoh ini saya mengurangi datetime2 skala ke 0:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.5555555'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
Hasil:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:31 | 2025-05-21 10:16:00 | +---------------------+---------------------+
Dalam hal ini, datetime2 nilai tidak lagi termasuk bagian pecahan. Kedua tipe sekarang memiliki panjang karakter yang sama (19 posisi).
Tapi tetap ada perbedaan.
datetime2 value menghormati nilai detik, meskipun dalam hal ini detiknya telah dibulatkan. Seperti yang disebutkan, waktu kecil komponen nilai detik selalu disetel ke nol, dan dalam hal ini, menitnya telah dibulatkan.
Alasan datetime2 komponen detik dibulatkan ke atas karena bagian pecahannya adalah 5 atau lebih tinggi. Jika kita mengurangi bagian pecahan, tidak ada pembulatan yang dilakukan:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.4444444'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
Hasil:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
Namun, waktu kecil menit nilai terus dibulatkan.
Contoh 3 – Menetapkan Nilai dari Literal String
Pada contoh sebelumnya, waktu kecil nilai ditetapkan dengan menyetelnya ke nilai yang sama dengan datetime2 nilai. Ketika kami melakukannya, SQL Server melakukan konversi implisit agar data "sesuai" dengan tipe data baru.
Namun, jika kami mencoba menetapkan literal string yang sama ke smalldatetime variabel, kami mendapatkan kesalahan:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime SET @thedatetime2 = '2025-05-21 10:15:30.4444444' SET @thesmalldatetime = '2025-05-21 10:15:30.4444444' SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
Hasil:
Msg 295, Level 16, State 3, Line 5 Conversion failed when converting character string to smalldatetime data type.
Itu karena waktu kecil hanya menerima literal string yang memiliki 3 atau kurang pecahan detik.
Anda mungkin berharap bahwa itu tidak akan menerima literal string dengan apa saja pecahan detik, mengingat itu tidak termasuk pecahan detik, tapi bukan itu masalahnya. Dengan senang hati menerima 3 detik pecahan, tetapi tidak lebih.
Jadi untuk mengatasi masalah ini, kita perlu mengurangi bagian pecahan menjadi hanya 3 (atau kurang) tempat desimal.
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.4444444'; SET @thesmalldatetime = '2025-05-21 10:15:30.444'; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
Hasil:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
datetime2 type tidak memiliki batasan ini, bahkan saat menggunakan skala 0.
Contoh 4 – Ukuran Penyimpanan
waktu kecil tipe data memiliki ukuran penyimpanan tetap 4 byte. Ini adalah salah satu dari sedikit manfaat smalldatetime memiliki lebih dari datetime2 .
datetime2 dapat berupa 6, 7, atau 8 byte, tergantung pada presisinya. Jadi datetime2 value akan selalu menggunakan penyimpanan minimal 2 byte lebih banyak daripada smalldatetime nilai.
Microsoft menyatakan bahwa datetime2 type juga menggunakan 1 byte tambahan untuk menyimpan presisinya, dalam hal ini akan menggunakan setidaknya 3 byte lebih dari smalldatetime .
Namun, ini mungkin 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 @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30'; SET @thesmalldatetime = @thedatetime2; SELECT DATALENGTH(@thedatetime2) AS 'datetime2', DATALENGTH(@thesmalldatetime) AS 'smalldatetime';
Hasil
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 6 | 4 | +-------------+-----------------+
Tetapi jika kita mengonversinya menjadi varbinary , kita mendapatkan yang berikut:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30'; SET @thesmalldatetime = @thedatetime2; SELECT DATALENGTH(CAST(@thedatetime2 AS varbinary(10))) AS 'datetime2', DATALENGTH(CAST(@thesmalldatetime AS varbinary(10))) AS 'smalldatetime';
Hasil
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 7 | 4 | +-------------+-----------------+
Jadi datetime2 menggunakan byte ekstra saat dikonversi ke varbinary . Banyak pengembang berasumsi bahwa mengonversi ke varbinary mewakili bagaimana SQL Server benar-benar menyimpan nilai tanggal dan waktu.
Ini hanya sebagian benar sekalipun. 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.
Contoh berikut menunjukkan hal ini. Ini menunjukkan bahwa ketika data disimpan dalam kolom database, kami mendapatkan panjang 6 byte untuk datetime2 vs 4 byte untuk smalldatetime .
Contoh 5 – Ukuran Penyimpanan untuk Data Tersimpan
Dalam contoh ini, saya membuat database dan menggunakan COL_LENGTH
untuk mengembalikan panjang setiap kolom, dalam byte. Saya kemudian memasukkan datetime2 dan waktu kecil nilai ke dalamnya dan gunakan DBCC PAGE()
untuk menemukan panjang data aktual dalam file halaman. Ini menunjukkan kepada kita ruang penyimpanan yang digunakan setiap tipe data saat disimpan dalam database.
Buat basis data:
CREATE DATABASE CompareTypes;
Buat tabel:
USE CompareTypes; CREATE TABLE Datetime2vsSmalldatetime ( TheDateTime2 datetime2(0), TheSmallDateTime smalldatetime );
Dalam hal ini saya membuat dua kolom – satu adalah datetime2(0) kolom dan yang lainnya adalah waktu kecil kolom.
Periksa Panjang Kolom
Periksa panjang (dalam byte) setiap kolom:
SELECT COL_LENGTH ( 'dbo.Datetime2vsSmalldatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsSmalldatetime' , 'TheSmallDateTime' ) AS 'smalldatetime';
Hasil:
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 6 | 4 | +-------------+-----------------+
Jadi kita melihat bahwa datetime2(0) kolom memiliki panjang 6 byte, dibandingkan dengan smalldatetime panjangnya 4 byte.
Sisipkan Data
Sekarang mari kita lihat ukuran penyimpanan dari nilai tanggal dan waktu aktual saat disimpan di SQL Server. Kita dapat menggunakan DBCC PAGE()
untuk memeriksa halaman sebenarnya dalam file data.
Tapi pertama-tama, kita perlu memasukkan data ke dalam kolom kita.
Masukkan data:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30'; INSERT INTO Datetime2vsSmalldatetime ( TheSmallDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Pilih data (hanya untuk memeriksanya):
SELECT * FROM Datetime2vsSmalldatetime;
Hasil:
+---------------------+---------------------+ | TheDateTime2 | TheSmallDateTime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
Menggunakan DBCC PAGE()
Di sinilah kami menggunakan DBCC PAGE()
untuk memeriksa halaman sebenarnya dalam file data.
Pertama, kita akan menggunakan DBCC IND()
untuk menemukan PagePID:
DBCC IND('CompareTypes', 'dbo.Datetime2vsSmalldatetime', 0);
Hasil (menggunakan keluaran vertikal):
-[ RECORD 1 ]------------------------- PageFID | 1 PagePID | 308 IAMFID | NULL IAMPID | NULL ObjectID | 1205579333 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043039744 iam_chain_type | In-row data PageType | 10 IndexLevel | NULL NextPageFID | 0 NextPagePID | 0 PrevPageFID | 0 PrevPagePID | 0 -[ RECORD 2 ]------------------------- PageFID | 1 PagePID | 344 IAMFID | 1 IAMPID | 308 ObjectID | 1205579333 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043039744 iam_chain_type | In-row data PageType | 1 IndexLevel | 0 NextPageFID | 0 NextPagePID | 0 PrevPageFID | 0 PrevPagePID | 0
Ini mengembalikan dua catatan. Kami tertarik dengan PageType dari 1 (catatan ke-2). Kami ingin PagePID dari catatan itu. Dalam hal ini PagePID adalah 344 .
Sekarang kita dapat mengambil PagePID itu dan menggunakannya sebagai berikut:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 344, 3);
Ini menghasilkan banyak data, tetapi kami terutama tertarik pada bagian berikut:
Slot 0 Column 1 Offset 0x4 Length 6 Length (physical) 6 TheDateTime2 = 2025-05-21 10:15:30 Slot 0 Column 2 Offset 0xa Length 4 Length (physical) 4 TheSmallDateTime = 2025-05-21 10:16:00.000
Ini menunjukkan bahwa waktu kecil memiliki panjang 4 byte dan datetime2(0) memiliki 6 byte saat disimpan dalam database.
Jadi dalam hal ini, hanya ada perbedaan 2 byte, tetapi datetime2(0) lebih akurat dan mematuhi standar ANSI dan ISO 8601.