ในเอกสารมีการระบุไว้อย่างชัดเจนว่ารูปแบบที่ปลอดภัยเท่านั้นเป็นรูปแบบที่ฉันแสดงในตอนต้นของคำถาม:
yyyyMMdd -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff -- date dash separated, date/time separated by T
อย่างไรก็ตามเมื่อไม่นานมานี้ข้าพเจ้าได้ทราบว่ามีรูปแบบที่สามที่มีภูมิคุ้มกันเท่าเทียมกับภาษาหรือการตั้งค่ารูปแบบวันที่:
yyyyMMdd hh:mm:ss.fff -- unseparated date, no T separator
TL; DR: นี่เป็นเรื่องจริง สำหรับและdatetime
smalldatetime
อ่านต่อไปสำหรับเวอร์ชั่นที่ยาวขึ้นและพิสูจน์ได้มากเท่าที่คุณจะได้รับ
มีช่องโหว่ที่อธิบายสิ่งนี้ - ในขณะที่เนื้อหาข้อความหลักไม่ยอมรับyyyyMMdd hh:...
ว่าเป็นรูปแบบที่ปลอดภัยจากการแปลภาษาหรือการแปลรูปแบบวันที่มีการประกาศแจ้งเล็กน้อยซึ่งระบุว่าส่วนวันที่ของสตริงดังกล่าวไม่ได้รับการตรวจสอบ
มันค่อนข้างแตกต่างจากฉันที่จะเพียงแค่ใช้เอกสารที่คำของมันมักจะ คุณสามารถพูดได้ว่าฉันค่อนข้างสงสัย และภาษาก็คลุมเครือที่นี่เช่นกัน - เพียงแค่ระบุว่านี่เป็นเรื่องเกี่ยวกับการรวมกันของวันที่และเวลาโดยไม่เรียกพื้นที่ออกมาอย่างชัดเจน (นั่นอาจเป็นผลตอบแทนการขนส่ง นอกจากนี้ยังบอกว่ามันไม่ใช่หลายภาษาซึ่งหมายความว่ามันอาจล้มเหลวในบางภาษา แต่เราจะพบในไม่ช้าว่ามันไม่ถูกต้องเช่นกัน
ดังนั้นฉันจึงออกเดินทางเพื่อพิสูจน์ว่าการผสมภาษา / รูปแบบวันที่ไม่สามารถทำให้รูปแบบเฉพาะนี้ล้มเหลว
ก่อนอื่นฉันสร้าง SQL ไดนามิกขึ้นเล็กน้อยสำหรับแต่ละภาษา:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
สิ่งนี้สร้างผลลัพธ์ 34 แถวดังนี้:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Deutsch';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Français';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'日本語';
...
EXEC sys.sp_executesql @sql, N'@lang sysname', N'简体中文';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Arabic';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'ไทย';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'norsk (bokmål)';
ฉันคัดลอกผลลัพธ์นั้นไปยังหน้าต่างแบบสอบถามใหม่และเหนือกว่านั้นฉันสร้างรหัสนี้ซึ่งหวังว่าจะพยายามแปลงวันที่เดียวกันนั้น (วันที่ 13 มีนาคม) เป็นวันที่ 3 ของเดือนที่ 13 อย่างน้อยหนึ่งกรณี:
DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';
Nope ydm
ทุกภาษาทำงานเพียงแค่หาใน ฉันลองทุกรูปแบบอื่นด้วยและทุกประเภทวันที่ / เวลา 34 Conversion ที่ประสบความสำเร็จถึง 13 มีนาคมทุกครั้ง
ดังนั้นฉันจึงยอมรับ @AndriyM และ @ErikE ว่ามีรูปแบบที่ปลอดภัยเป็นอันดับสาม ฉันจะเก็บเรื่องนี้ไว้ในใจสำหรับโพสต์ในอนาคต แต่ฉันได้ตีกลองเกี่ยวกับอีกสองในหลาย ๆ ที่ฉันจะไม่ไล่ตามพวกเขาทั้งหมดและแก้ไขให้ถูกต้องในตอนนี้
โดยการขยายคุณจะคิดว่าอันนี้ปลอดภัย แต่ไม่มี:
yyyyMMddThh:mm:ss.fff -- unseparated date, T separator
ฉันคิดว่าในทุกภาษานี้จะให้ผลเทียบเท่า:
ข่าวสารเกี่ยวกับ 241 ระดับ 16 สถานะ 1
การแปลงบรรทัด 8
ล้มเหลวเมื่อทำการแปลงวันที่และ / หรือเวลาจากสตริงอักขระ
เพื่อความสมบูรณ์มีรูปแบบที่ปลอดภัยสี่ แต่มันมีความปลอดภัยเพียงสำหรับการแปลงให้เป็นวันใหม่ / ประเภทเวลา ( date
, datetime2
, datetimeoffset
) ในกรณีเหล่านี้การตั้งค่าภาษาไม่สามารถแทรกแซง:
yyyy-MM-dd hh:mm:...
อย่างไรก็ตามฉันขอแนะนำอย่างยิ่งต่อการใช้งานเพราะใช้ได้เฉพาะกับรุ่นที่ใหม่กว่าและรุ่นเก่ายังคงมีการใช้งานจำนวนมากในประสบการณ์ของฉัน เหตุใดจึงมีเครื่องหมายขีดคั่นเมื่อทุกที่อื่น (หรืออันที่จริงในรหัสเดียวกันนั้นหากการเปลี่ยนแปลงชนิดข้อมูล) คุณต้องลบออก?
SET LANGUAGE Deutsch;
DECLARE @dashes char(10) = '2017-03-07 03:34';
DECLARE @d date = @dashes, @dt datetime = @dashes, @dt2 datetime2 = @dashes;
SELECT DATENAME(MONTH,@d), DATENAME(MONTH,@dt), DATENAME(MONTH,@dt2);
แม้จะได้รับสตริงของแหล่งข้อมูลเดียวกันการแปลงก็ให้ผลลัพธ์ที่แตกต่างกันมาก:
März Juli März
รูปแบบที่เหมาะกับวันที่และเวลา ( yyyyMMdd
) จะยังมักจะทำงานให้กับวันที่และชนิดใหม่ ๆ ดังนั้น IMHO ใช้มันเสมอ และเมื่อกำหนดรูปแบบที่สามสำหรับประเภทที่มีวันที่ / เวลา ( yyyyMMdd hh:...
) สิ่งนี้จะช่วยให้คุณมีความสอดคล้องมากยิ่งขึ้น - แม้ว่าองค์ประกอบของวันที่จะสามารถอ่านได้น้อยลง
ตอนนี้จะใช้เวลาไม่กี่ปีที่ฉันจะให้หรือใช้เพื่อให้เป็นนิสัยของการสาธิตรูปแบบที่ปลอดภัยทั้งสามเมื่อฉันพูดคุยเกี่ยวกับการเป็นตัวแทนสตริงของวันที่