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

Memecahkan Masalah saat Bekerja dengan Tanggal dan Waktu di SQL Server

Database Microsoft SQL Server menyimpan informasi tanggal dan waktu dalam berbagai format. Yang paling umum adalah DateTime , DateTime2 , dan Tanggal . Seperti yang terjadi dengan semua jenis data, masalah dapat terjadi dari waktu ke waktu. Dalam artikel ini, kami akan fokus pada pemecahan masalah beberapa masalah paling umum yang mungkin Anda hadapi saat bekerja dengan tipe data waktu dan tanggal SQL.

Masalah Terkait dengan Format Tanggal yang Berbeda Secara Regional

Format tanggal bervariasi secara global. Misalnya, orang Inggris menulis tanggal sebagai dd-mm-yyyy, sedangkan orang Amerika menulis tanggal dalam format mm-dd-yyyy. Dengan cara ini, tanggal yang sama, 31 Desember 2020, ditulis sebagai 31-12-2020 dalam format tanggal Inggris dan sebagai 31-12-2020 dalam format Amerika.

Masalah ketidakmampuan dapat muncul jika Anda tidak menentukan tanggal dalam format yang sesuai dengan pengaturan bahasa instans SQL Server Anda.

Skrip berikut mengonversi string teks dengan informasi tanggal ke dalam format DATETIME. Pengaturan bahasa diatur ke BRITISH. String teks berisi 31-12-2020 04:25:30 .

Jika Anda memasukkan string ini ke dalam format DATETIME, 31 akan dianggap sebagai hari, sedangkan 12 akan menjadi bulan secara default. Oleh karena itu, konversi akan berhasil seperti yang ditunjukkan dari output:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Namun, jika Anda mencoba mengonversi string yang berisi tanggal 31-12-2020 ke format DATETIME menggunakan US_ENGLISH pengaturan bahasa, Anda akan menerima kesalahan seperti yang ditunjukkan di bawah ini:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Kesalahan terjadi karena setelan bahasa US_ENGLISH menentukan 31 sebagai bulan bukan hari. Sebagai bulan nilai tidak boleh lebih besar dari 12, kami menerima kesalahan nilai di luar rentang .

Jika Anda menetapkan tanggal sebagai 31-12-2020 dan kemudian mengonversi string tanggal ke DATETIME menggunakan setelan US_ENGLISH, Anda akan melihat konversi yang berhasil:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Demikian pula, mengonversi 31-12-2020 string tanggal di bawah pengaturan bahasa INGGRIS juga menyebabkan kesalahan – 31 diperlakukan sebagai bulan, itu tidak mungkin.

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Untuk mengonversi tanggal Anda secara akurat terlepas dari pengaturan bahasa, Anda dapat menggunakan standar ISO 8601 untuk format tanggal. Untuk mematuhi standar ini, tentukan tanggal sebagai yyyy-mm-ddThh:mm:ss .

Misalnya, string tanggal 31-12-2020T04:25:30 berhasil dikonversi ke tipe data DATETIME di bawah setelan bahasa INGGRIS:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Skrip berikut menunjukkan string yang sama yang diubah menjadi DATETIME dengan setelan US_ENGLISH:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Pertimbangan Zona Waktu

Anda mungkin ingin mengembangkan beberapa aplikasi database SQL Server untuk audiens global. Untuk itu, Anda mungkin perlu menambahkan informasi zona waktu ke tipe data tanggal dan waktu.

Di SQL Server, tipe data DATETIMEOFFSET menyimpan informasi tanggal dan waktu bersama dengan offset zona waktu. Offset zona waktu ditetapkan sebagai UTC +/- jumlah jam.

Misalnya, skrip berikut menggunakan metode SYSDATETIMEOFFSET() untuk mendapatkan informasi tanggal, waktu, dan offset dari sistem yang menjalankan instance SQL Server Anda. Nilai yang dikembalikan oleh fungsi SYSDATETIMEOFFSET() disimpan dalam variabel tipe DATETIMEOFFSET @dateoffset. Nilai variabel @dateoffset dicetak menggunakan pernyataan SELECT:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT @dateoffset

Output di bawah ini menunjukkan melihat tanggal dan waktu saat ini dan nilai offset. Dalam hal ini, ini adalah +02:00.

Anda juga bisa mendapatkan hanya nilai offset dari variabel DATETIMEOFFSET. Untuk melakukannya, Anda harus meneruskan variabel tipe DATETIMEOFFSET sebagai nilai parameter kedua ke fungsi DATENAME(). Parameter pertama untuk metode DATENAME() harus tzoffset .

Skrip berikut mengembalikan bagian offset waktu dari tanggal sistem saat ini:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT DATENAME(tzoffset, @dateoffset)

Untuk membuat variabel DATETIMEOFFSET kustom, tentukan nilai untuk bagian offset tanggal, waktu, dan waktu. Misalnya, dalam skrip berikut, nilai untuk tanggal adalah 22-02-2015 , nilai untuk porsi waktu adalah 23:59:59:999 , dan nilai offset waktu adalah +05:00 .

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT @dateoffset

Terakhir, Anda juga dapat memperbarui informasi offset waktu menggunakan SWITCHOFFSET() fungsi.

Anda harus melewati DATETIMEOFFSET ketik variabel sebagai nilai parameter pertama dan berikan offset waktu baru sebagai nilai parameter kedua ke SWITCHOFFSET fungsi.

Skrip berikut memperbarui nilai offset waktu untuk variabel DATETIMEOFFSET dari +05:00 hingga +09:00.

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT SWITCHOFFSET(@dateoffset, '+09:00');

Memilih Catatan Menggunakan ANTARA Operator dengan DateTime

ANTARA operator di server SQL memfilter catatan di antara rentang nilai yang diteruskan ke sana.

Anda dapat menggunakan operator ANTARA untuk mengembalikan catatan antara dua tanggal. Namun, Anda harus ekstra hati-hati saat menggunakannya untuk memfilter catatan dengan tanggal.

Misalnya, skrip berikut membuat Hostel dummy database dan menambahkan satu Siswa tabel untuk itu.

CREATE DATABASE Hostel

USE Hostel
CREATE TABLE Student

(
Id INT PRIMARY KEY IDENTITY(1,1),
Name VARCHAR (50) NOT NULL,
Gender VARCHAR (50),
BirthDate DateTime
)

Skrip berikutnya menambahkan beberapa catatan dummy ke Siswa meja. Tanggal Lahir kolom Siswa meja menyimpan tanggal. Dari skrip ini, Anda dapat melihat bahwa dua siswa Sara dan Nik memiliki tanggal lahir yang sama. Namun, waktu kelahirannya berbeda:

INSERT INTO Student
VALUES ('Jack', 'Male', '2017-06-30 16:30:35'),
('Sara', 'Female', '2015-02-22 00:00:00'),
('Elisa', 'Female',  '2020-03-16 22:24:39'),
('Nik', 'Male',  '2015-02-22 09:45:55'),
('Jos', 'Male',  '2015-03-25 11:55:20')

Anda akan berpikir bahwa operator BETWEEN dapat digunakan untuk mengambil catatan semua siswa yang lahir pada 22-02-2015.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22'

Tetapi jika Anda menjalankan skrip di atas, Anda akan melihat bahwa hanya satu catatan yang dikembalikan, meskipun waktu bagian juga disertakan.

Alasannya adalah bahwa operator ANTARA memperlakukan secara default nilai DATETIME 22-02-2015 sebagai 22-02-2015 00:00:00 . Oleh karena itu, operator ANTARA dalam kueri di atas menelusuri catatan dengan Tanggal Lahir nilai antara 22-02-2015 00:00:00 dan 22-02-2015 00:00:00 .

Untuk mengatasi masalah ini, kita harus menentukan porsi waktu saat menggunakan operator BETWEEN dengan tipe data DATETIME.

Skrip berikut akan mengembalikan semua rekaman antara 22-02-2015 00:00:00 dan 22-02-2015 23:59:59:999 . Porsi waktu untuk batas tanggal atas adalah 23:59:999.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22 23:59:59:999';

Dalam output, kami mendapatkan dua catatan untuk Tanggal Lahir 22-02-2015 .

Masalah Terkait Rentang Tanggal

Tipe data DATETIME hanya mendukung tahun 1753 hingga 9999. Oleh karena itu, jika Anda mencoba menyimpan tanggal dengan nilai tahun lebih besar dari 9999 atau lebih kecil dari 1753, Anda akan mendapatkan kesalahan.

Skrip berikut mencoba mengonversi 1392-12-31 string tanggal. 1392 kurang dari 1753. Oleh karena itu, kami memiliki kesalahan nilai di luar rentang.

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME);

Untuk menyimpan nilai tahun kurang dari 1753 , Anda dapat menggunakan DATETIME2 tipe data. Ini menyimpan nilai tahun dari 0000 hingga 9999.

Skrip berikut berhasil mengonversi string tanggal 1392-12-31 menjadi tipe data DATETIME2:

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME2);

Menggunakan TRY_COVERT untuk Konversi DateTime

Fungsi CONVERT di SQL Server mengubah data dari satu tipe ke tipe lainnya. Anda dapat menggunakannya untuk mengonversi format data tipe tanggal ke format lain dan sebaliknya. Namun, jika konversi gagal, fungsi CONVERT memunculkan kesalahan.

Misalnya, kami mengonversi string 31-31-2015 ke format DATETIME:

DECLARE @date VARCHAR(50) = '2015-31-13';
SELECT  CONVERT(DATETIME, @date ,105) as DOB_CONV

Jika Anda ingin nilai NULL dikembalikan saat konversi gagal alih-alih pesan kesalahan, gunakan TRY_CONVERT fungsi. Metode ini tidak akan membiarkan aplikasi mogok – ini hanya mengembalikan nilai NULL.

DECLARE @date VARCHAR(50) = '2015-31-13';

SELECT  TRY_CONVERT(DATETIME, @date ,105) as DOB_CONV

Kesimpulan

Bekerja dengan SQL Server, Anda mungkin menghadapi banyak masalah yang merusak pengalaman Anda dan memperumit tugas. Mengetahui masalah yang paling umum adalah, di sisi lain, metode yang paling efisien untuk mencegahnya terjadi. Itulah mengapa kami mendedikasikan artikel ini untuk memecahkan masalah ketidaknyamanan yang mungkin terjadi selama Anda bekerja dengan informasi tentang tanggal dan waktu.

Perhatikan juga bahwa alat modern untuk bekerja dengan database SQL Server dapat membuat kehidupan spesialis DB lebih sederhana. Secara khusus, dbForge Studio untuk SQL Server menyediakan fitur Editor Data Visual untuk diterapkan saat menangani tanggal. Anda dapat menggunakannya untuk melihat dan mengedit tanggal dengan cara yang paling ramah pengguna.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SET DATEFIRST – Atur Hari Pertama dalam seminggu di SQL Server

  2. Apa cara tercepat untuk menyisipkan banyak data secara massal di SQL Server (klien C#)

  3. Apakah saya benar-benar perlu menggunakan SET XACT_ABORT ON?

  4. Sisipkan Massal File CSV yang Dikutip Sebagian di SQL Server

  5. Apakah ada cara untuk mengakses nilai baris sebelumnya dalam pernyataan SELECT?