Sql Server string ke konversi tanggal


186

Saya ingin mengonversi string seperti ini:

'10/15/2008 10:06:32 PM'

ke dalam nilai DATETIME yang setara di Sql Server.

Di Oracle, saya akan mengatakan ini:

TO_DATE('10/15/2008 10:06:32 PM','MM/DD/YYYY HH:MI:SS AM')

Pertanyaan ini menyiratkan bahwa saya harus mengurai string ke salah satu format standar , dan kemudian mengonversi menggunakan salah satu kode itu. Itu tampak menggelikan untuk operasi duniawi seperti itu. Apakah ada cara yang lebih mudah?


Jawaban:


28

SQL Server (2005, 2000, 7.0) tidak memiliki cara yang fleksibel, atau bahkan tidak fleksibel, untuk mengambil datetime yang terstruktur secara sewenang-wenang dalam format string dan mengubahnya menjadi tipe data datetime.

Dengan "sewenang-wenang", maksud saya "bentuk yang orang yang menulisnya, meskipun mungkin bukan Anda atau saya atau seseorang di sisi lain planet ini, akan dianggap sebagai intuitif dan sangat jelas." Terus terang, saya tidak yakin ada algoritma seperti itu.


32
ada algoritma seperti itu, Oracle telah menerapkannya, dan kurangnya SQL Server setara adalah rasa sakit yang konstan.
matao

19
@matao jadi tolong beri tahu kami, bagaimana Oracle secara ajaib menentukan apakah pengguna yang mengetik 9/6/12berarti 6 September 2012, 9 Juni 2012, 6 Desember 2009, atau yang lainnya?
Aaron Bertrand

13
jangan khawatir, di sini: techonthenet.com/oracle/functions/to_date.php Jelas itu harus menjadi format yang konsisten yang Anda tentukan oleh pengembang, tetapi jauh lebih fleksibel daripada segelintir masker format yang diberikan MS kepada Anda, yang menghasilkan penguraian khusus yang menyakitkan .
matao

3
@JosphStyons menyadari fungsi TO_DATE Oracle, seperti yang ditunjukkan dalam sampelnya. Dia ingin tahu apakah ada cara untuk mengubah tanggal-sebagai-string tanpa harus mengetahui format / struktur string. SQL tidak melakukan itu, dan tentu saja TO_DATE Oracle juga tidak melakukannya.
Philip Kelley

23
@ PhilipKelley Saya tidak melihat di mana OP ingin tahu bagaimana melakukannya tanpa harus tahu formatnya. Dia secara eksplisit mengatakan dia tahu format dan bertanya apakah SQL Server memiliki sesuatu yang setara dengan TO_DATE, yaitu sesuatu yang memungkinkan pengembang untuk memasukkan string format sewenang-wenang.
neverfox

306

Coba ini

Cast('7/7/2011' as datetime)

dan

Convert(varchar(30),'7/7/2011',102)

Lihat CAST dan CONVERT (Transact-SQL) untuk lebih jelasnya.


14
Ini adalah cara yang tepat untuk melakukannya, dan harus ditandai sebagai jawaban yang benar. Perhatikan bahwa ini Cast('2011-07-07' as datetime)juga berfungsi, dan menghilangkan ambiguitas dalam urutan bulan dan hari.
Joe DeRose

Ini tidak berfungsi ketika bulan> 12. Format ini mengharapkan format mm / hh / tttt
Chakri

Gunakan Konversi (varchar (30), '7/7/2011', 103) ketika mengkonversi dari dd / mm / yyyy
Matias Masso

2
@Chakri jika teman kencan Anda menggunakan dd / mm / yyyy SET DATEFORMAT dmysebelum permintaan Anda
Nathan Griffiths

49

Jalankan ini melalui prosesor kueri Anda. Ini memformat tanggal dan / atau waktu seperti itu dan salah satunya akan memberi Anda apa yang Anda cari. Tidak akan sulit untuk beradaptasi:

Declare @d datetime
select @d = getdate()

select @d as OriginalDate,
convert(varchar,@d,100) as ConvertedDate,
100 as FormatValue,
'mon dd yyyy hh:miAM (or PM)' as OutputFormat
union all
select @d,convert(varchar,@d,101),101,'mm/dd/yy'
union all
select @d,convert(varchar,@d,102),102,'yy.mm.dd'
union all
select @d,convert(varchar,@d,103),103,'dd/mm/yy'
union all
select @d,convert(varchar,@d,104),104,'dd.mm.yy'
union all
select @d,convert(varchar,@d,105),105,'dd-mm-yy'
union all
select @d,convert(varchar,@d,106),106,'dd mon yy'
union all
select @d,convert(varchar,@d,107),107,'Mon dd, yy'
union all
select @d,convert(varchar,@d,108),108,'hh:mm:ss'
union all
select @d,convert(varchar,@d,109),109,'mon dd yyyy hh:mi:ss:mmmAM (or PM)'
union all
select @d,convert(varchar,@d,110),110,'mm-dd-yy'
union all
select @d,convert(varchar,@d,111),111,'yy/mm/dd'
union all
select @d,convert(varchar,@d,12),12,'yymmdd'
union all
select @d,convert(varchar,@d,112),112,'yyyymmdd'
union all
select @d,convert(varchar,@d,113),113,'dd mon yyyy hh:mm:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,114),114,'hh:mi:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,120),120,'yyyy-mm-dd hh:mi:ss(24h)'
union all
select @d,convert(varchar,@d,121),121,'yyyy-mm-dd hh:mi:ss.mmm(24h)'
union all
select @d,convert(varchar,@d,126),126,'yyyy-mm-dd Thh:mm:ss:mmm(no spaces)'

47

Di SQL Server Denali, Anda akan dapat melakukan sesuatu yang mendekati apa yang Anda cari. Tapi Anda masih tidak bisa hanya melewatkan string tanggal aneh yang ditentukan sewenang-wenang dan mengharapkan SQL Server untuk mengakomodasi. Ini adalah salah satu contoh menggunakan sesuatu yang Anda posting dalam jawaban Anda sendiri. FORMAT () berfungsi dan juga dapat menerima lokal sebagai argumen opsional - didasarkan pada format .Net, jadi sebagian besar jika tidak semua format token yang Anda harapkan akan ada di sana.

DECLARE @d DATETIME = '2008-10-13 18:45:19';

-- returns Oct-13/2008 18:45:19:
SELECT FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss');

-- returns NULL if the conversion fails:
SELECT TRY_PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

-- returns an error if the conversion fails:
SELECT PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

Saya sangat menyarankan Anda untuk mengambil kendali lebih besar dan membersihkan input tanggal Anda. Hari-hari membiarkan orang mengetik tanggal menggunakan format apa pun yang mereka inginkan ke dalam bidang bentuk teks bebas harus jauh di belakang kita sekarang. Jika seseorang masuk 8/9/2011 apakah itu 9 Agustus atau 8 September? Jika Anda membuat mereka memilih tanggal pada kontrol kalender, maka aplikasi dapat mengontrol format. Tidak peduli seberapa banyak Anda mencoba untuk memprediksi perilaku pengguna Anda, mereka akan selalu mencari cara bodoh untuk memasukkan tanggal yang tidak Anda rencanakan.

Sampai Denali, saya pikir @Ovidiu memiliki saran terbaik sejauh ini ... ini dapat dibuat cukup sepele dengan menerapkan fungsi CLR Anda sendiri. Kemudian Anda dapat menulis case / switch sebanyak mungkin format non-standar yang Anda inginkan.


UPDATE untuk @dhergert :

SELECT TRY_PARSE('10/15/2008 10:06:32 PM' AS DATETIME USING 'en-us');
SELECT TRY_PARSE('15/10/2008 10:06:32 PM' AS DATETIME USING 'en-gb');

Hasil:

2008-10-15 22:06:32.000
2008-10-15 22:06:32.000

Anda masih perlu memiliki informasi penting lainnya terlebih dahulu. Anda tidak dapat menggunakan T-SQL asli untuk menentukan apakah 6/9/2012tanggal 9 Juni atau 6 September.


1
Saya pikir pertanyaannya adalah bagaimana mengubah string menjadi datetime, bukan datetime menjadi string.
David Hergert

1
TRY_PARSE sempurna. Kami memiliki masalah dengan menguraikan tanggal 'Kamis 22 Sep 2016', terima kasih telah berbagi!
Simon

11

Untuk masalah ini solusi terbaik yang saya gunakan adalah memiliki fungsi CLR di Sql Server 2005 yang menggunakan salah satu fungsi DateTime.Parse atau ParseExact untuk mengembalikan nilai DateTime dengan format yang ditentukan.


11

Gunakan ini:

SELECT convert(datetime, '2018-10-25 20:44:11.500', 121) -- yyyy-mm-dd hh:mm:ss.mmm

Dan lihat tabel dalam dokumentasi resmi untuk kode konversi.


8

kenapa tidak mencoba

select convert(date,'10/15/2011 00:00:00',104) as [MM/dd/YYYY]

format tanggal dapat ditemukan di SQL Server Helper> Format Tanggal SQL Server


Contoh kode Anda tidak berfungsi. "Konversi gagal ketika mengubah tanggal dan / atau waktu dari string karakter."
César León

5
Seharusnya select convert(date,'10/15/2011 00:00:00',101). Rincian lebih lanjut tentang format dan mengapa 101, di docs.microsoft.com/en-us/sql/t-sql/functions/…
anotherUser

1
Delapan orang telah memilih jawaban ini dan bahkan tidak berhasil ...
David Klempfner

4

Butuh waktu sebentar untuk mencari tahu, jadi ini dia kalau-kalau bisa membantu seseorang:

Di SQL Server 2012 dan lebih baik Anda dapat menggunakan fungsi ini:

SELECT DATEFROMPARTS(2013, 8, 19);

Inilah cara saya mengekstraksi bagian tanggal untuk dimasukkan ke dalam fungsi ini:

select
DATEFROMPARTS(right(cms.projectedInstallDate,4),left(cms.ProjectedInstallDate,2),right( left(cms.ProjectedInstallDate,5),2)) as 'dateFromParts'
from MyTable

3

Halaman ini memiliki beberapa referensi untuk semua konversi datetime tertentu yang tersedia untuk fungsi CONVERT. Jika nilai Anda tidak jatuh ke dalam salah satu pola yang dapat diterima, maka saya pikir yang terbaik adalah pergi dengan rute ParseExact.


tautan rusak.
Michael Potter

3

Secara pribadi jika Anda berurusan dengan format dinding yang sewenang-wenang atau sepenuhnya, asalkan Anda tahu apa yang mereka lakukan sebelumnya atau yang akan terjadi maka cukup gunakan regexp untuk menarik bagian tanggal yang Anda inginkan dan membentuk komponen tanggal / datetime yang valid.


1

Saya tahu ini adalah posting lama yang jahat dengan banyak jawaban tetapi banyak orang berpikir bahwa mereka PERLU untuk memisahkan hal-hal dan menyatukannya kembali atau mereka bersikeras bahwa tidak ada cara untuk secara implisit melakukan konversi yang diminta oleh OP asli. .

Untuk meninjau dan berharap memberikan jawaban yang mudah kepada orang lain dengan pertanyaan yang sama, OP bertanya bagaimana mengkonversi '10 / 15/2008 10:06:32 PM 'menjadi DATETIME. Sekarang, SQL Server memang memiliki beberapa dependensi bahasa untuk konversi sementara tetapi jika bahasanya adalah bahasa Inggris atau yang serupa, ini menjadi masalah sederhana ... lakukan saja konversi dan jangan khawatir tentang formatnya. Misalnya (dan Anda dapat menggunakan CONVERT atau CAST) ...

 SELECT UsingCONVERT = CONVERT(DATETIME,'10/15/2008 10:06:32 PM')
        ,UsingCAST   = CAST('10/15/2008 10:06:32 PM' AS DATETIME)
;

... dan itu menghasilkan jawaban ikuti, yang keduanya benar.

masukkan deskripsi gambar di sini

Seperti yang mereka katakan di iklan TV, "Tapi tunggu! Jangan pesan dulu! Tanpa biaya tambahan, itu bisa melakukan JAUH lebih banyak!"

Mari kita lihat kekuatan konversi temporal yang sebenarnya dengan DATETIME dan sebagian memeriksa kesalahan yang dikenal sebagai DATETIME2. Lihat format aneh yang DATETIME dapat tangani secara ajaib dan DATETIME2 tidak bisa. Jalankan kode berikut dan lihat ...

--===== Set the language for this example.
    SET LANGUAGE ENGLISH --Same a US-English
;
--===== Use a table constructor as if it were a table for this example.
 SELECT *
        ,DateTimeCONVERT  = TRY_CONVERT(DATETIME,StringDT)
        ,DateTimeCAST     = TRY_CAST(StringDT AS DATETIME)
        ,DateTime2CONVERT = TRY_CONVERT(DATETIME2,StringDT)
        ,DateTime2CAST    = TRY_CAST(StringDT AS DATETIME2)
   FROM (
         VALUES
         ('Same Format As In The OP'    ,'12/16/2001 01:51:01 PM')
        ,('Almost Normal'               ,'16 December, 2001 1:51:01 PM')
        ,('More Normal'                 ,'December 16, 2001 01:51:01 PM')
        ,('Time Up Front + Spaces'      ,'   13:51:01  16 December   2001')
        ,('Totally Whacky Format #01'   ,'  16  13:51:01  December   2001')
        ,('Totally Whacky Format #02'   ,'  16    December 13:51:01  2001  ')
        ,('Totally Whacky Format #03'   ,'  16    December 01:51:01  PM 2001  ')
        ,('Totally Whacky Format #04'   ,' 2001 16    December 01:51:01  PM ')
        ,('Totally Whacky Format #05'   ,' 2001    December 01:51:01  PM  16  ')
        ,('Totally Whacky Format #06'   ,' 2001 16    December  01:51:01 PM  ')
        ,('Totally Whacky Format #07'   ,' 2001 16    December  13:51:01 PM  ')
        ,('Totally Whacky Format #08'   ,' 2001 16  13:51:01 PM  December    ')
        ,('Totally Whacky Format #09'   ,'   13:51:01   PM  2001.12/16 ')
        ,('Totally Whacky Format #10'   ,'   13:51:01   PM  2001.December/16 ')
        ,('Totally Whacky Format #11'   ,'   13:51:01   PM  2001.Dec/16 ')
        ,('Totally Whacky Format #12'   ,'   13:51:01   PM  2001.Dec.16 ')
        ,('Totally Whacky Format #13'   ,'   13:51:01   PM  2001/Dec.16')
        ,('Totally Whacky Format #14'   ,'   13:51:01   PM  2001 . 12/16 ')
        ,('Totally Whacky Format #15'   ,'   13:51:01   PM  2001 . December / 16 ')
        ,('Totally Whacky Format #16'   ,'   13:51:01   PM  2001 . Dec /   16 ')
        ,('Totally Whacky Format #17'   ,'   13:51:01   PM  2001 . Dec .   16 ')
        ,('Totally Whacky Format #18'   ,'   13:51:01   PM  2001 / Dec .   16')
        ,('Totally Whacky Format #19'   ,'   13:51:01   PM  2001 . Dec -   16 ')
        ,('Totally Whacky Format #20'   ,'   13:51:01   PM  2001 - Dec -   16 ')
        ,('Totally Whacky Format #21'   ,'   13:51:01   PM  2001 - Dec .   16')
        ,('Totally Whacky Format #22'   ,'   13:51:01   PM  2001 - Dec /   16 ')
        ,('Totally Whacky Format #23'   ,'   13:51:01   PM  2001 / Dec -   16')
        ,('Just the year'               ,' 2001      ')
        ,('YYYYMM'                      ,' 200112      ')
        ,('YYYY MMM'                    ,'2001 Dec')
        ,('YYYY-MMM'                    ,'2001-Dec')
        ,('YYYY    .     MMM'           ,'2001    .     Dec')
        ,('YYYY    /     MMM'           ,'2001    /     Dec')
        ,('YYYY    -     MMM'           ,'2001    /     Dec')
        ,('Forgot The Spaces #1'        ,'2001December26')
        ,('Forgot The Spaces #2'        ,'2001Dec26')
        ,('Forgot The Spaces #3'        ,'26December2001')
        ,('Forgot The Spaces #4'        ,'26Dec2001')
        ,('Forgot The Spaces #5'        ,'26Dec2001 13:51:01')
        ,('Forgot The Spaces #6'        ,'26Dec2001 13:51:01PM')
        ,('Oddly, this doesn''t work'   ,'2001-12')
        ,('Oddly, this doesn''t work'   ,'12-2001')
        ) v (Description,StringDT)
;

Jadi, ya ... SQL Server TIDAK benar-benar memiliki metode yang cukup fleksibel dalam menangani semua jenis format temporal yang aneh dan tidak perlu penanganan khusus. Kami bahkan tidak perlu menghapus "PM" yang ditambahkan ke waktu 24 jam. Ini "PFM" (Sihir Freakin Murni).

Hal-hal akan sedikit berbeda tergantung pada BAHASA adalah bahwa Anda telah memilih untuk server Anda, tetapi banyak hal akan ditangani dengan cara baik.

Dan konversi "sihir otomatis" ini bukanlah sesuatu yang baru. Mereka sangat jauh ke belakang.


Jawaban baru yang jahat untuk pertanyaan lama yang jahat. Terima kasih!
JosephStyons

Terima kasih atas umpan baliknya, @JosephStyons.
Jeff Moden

0

Jika Anda ingin SQL Server mencoba dan mengetahuinya, gunakan saja CAST CAST ('apapun' AS datetime) Namun itu adalah ide yang buruk secara umum. Ada masalah dengan tanggal internasional yang akan muncul. Jadi seperti yang Anda temukan, untuk menghindari masalah itu, Anda ingin menggunakan format kanonik ODBC tanggal. Itu adalah format angka 120, 20 adalah format hanya untuk dua digit tahun. Saya tidak berpikir SQL Server memiliki fungsi built-in yang memungkinkan Anda untuk memberikan format yang diberikan pengguna. Anda dapat menulis sendiri dan bahkan mungkin menemukannya jika Anda mencari secara online.


Jika Anda memiliki tanggal internasional dalam satu kolom, saya benar-benar setuju bahwa menggunakan nomor format adalah ide yang bagus. Jika Anda memiliki tanggal internasional dan tanggal AS semua dicampur dalam satu kolom, tidak ada cara untuk menentukan perbedaan antara sesuatu seperti 7/6/2000 dan 6/7/2000 kecuali Anda memiliki kolom saudara yang menjelaskan formatnya. Itu sebabnya kualitas data pada sumbernya HARUS menjadi suatu hal. Jika Anda TAHU bahwa Anda memiliki, katakanlah, semua tanggal AS, biarkan konversi implisit melakukan hal mereka. Jika gagal, maka Anda tahu pasti bahwa sesuatu di kolom perlu diperbaiki.
Jeff Moden

0

mengkonversi string ke datetime di MSSQL secara implisit

create table tmp 
(
  ENTRYDATETIME datetime
);

insert into tmp (ENTRYDATETIME) values (getdate());
insert into tmp (ENTRYDATETIME) values ('20190101');  --convert string 'yyyymmdd' to datetime


select * from tmp where ENTRYDATETIME > '20190925'  --yyyymmdd 
select * from tmp where ENTRYDATETIME > '20190925 12:11:09.555'--yyyymmdd HH:MIN:SS:MS



Hai dan selamat datang di stackoverflow, dan terima kasih telah menjawab. Meskipun kode ini dapat menjawab pertanyaan, dapatkah Anda mempertimbangkan untuk menambahkan beberapa penjelasan untuk masalah apa yang Anda selesaikan, dan bagaimana Anda menyelesaikannya? Ini akan membantu pembaca di masa depan untuk memahami jawaban Anda dengan lebih baik dan belajar darinya.
Plutian

-4
dateadd(day,0,'10/15/2008 10:06:32 PM')

3
Selamat datang di StackOverflow! Harap edit jawaban Anda untuk menambahkan penjelasan untuk kode Anda. Pertanyaan ini sudah hampir sebelas tahun , dan sudah memiliki banyak jawaban yang jelas dan terangkat. Tanpa penjelasan dalam jawaban Anda , kualitasnya jauh lebih rendah dibandingkan dengan yang lain dan kemungkinan besar akan diturunkan atau dihapus. Menambahkan penjelasan itu akan membantu membenarkan keberadaan jawaban Anda di sini.
Das_Geek

Ya tapi posting "dijelaskan dengan baik", bahkan yang upvoted, terlalu rumit. Yang diposting di sini sebenarnya adalah salah satu yang lebih baik, dengan atau tanpa penjelasan,
Jeff Moden
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.