DateTime2 เทียบกับ DateTime ใน SQL Server


762

อันไหน:

เป็นวิธีที่แนะนำไปยังวันที่และเวลาการจัดเก็บใน SQL Server 2008+?

ฉันทราบถึงความแตกต่างของความแม่นยำ (และพื้นที่เก็บข้อมูลอาจ) แต่เมื่อไม่สนใจสิ่งเหล่านี้ตอนนี้มีเอกสารการปฏิบัติที่ดีที่สุดเรื่องเวลาที่จะใช้อะไรหรือบางทีเราควรจะใช้datetime2แค่นี้เท่านั้น?

คำตอบ:


641

เอกสาร MSDN สำหรับdatetimeแนะนำให้ใช้datetime2 นี่คือคำแนะนำของพวกเขา:

ใช้time, date, datetime2และ datetimeoffsetชนิดข้อมูลสำหรับการทำงานใหม่ ประเภทเหล่านี้สอดคล้องกับมาตรฐาน SQL พวกมันพกพาได้มากกว่า time, datetime2และdatetimeoffset ให้ความแม่นยำวินาที datetimeoffsetให้การสนับสนุนเขตเวลาสำหรับแอปพลิเคชันที่ปรับใช้ทั่วโลก

datetime2 มีช่วงวันที่ที่ใหญ่กว่าความแม่นยำของเศษส่วนเริ่มต้นที่มากขึ้นและความแม่นยำที่ผู้ใช้ระบุ นอกจากนี้ยังขึ้นอยู่กับความแม่นยำที่ผู้ใช้ระบุอาจใช้พื้นที่เก็บข้อมูลน้อยกว่า


46
ในขณะที่มีความแม่นยำเพิ่มขึ้นกับ datetime2 ลูกค้าบางคนไม่สนับสนุนวันที่เวลาหรือ datetime2 และบังคับให้คุณแปลงเป็นตัวอักษรสตริง หากคุณกังวลเกี่ยวกับความเข้ากันได้มากกว่าความแม่นยำให้ใช้
FistOfFury

4
ตัวเลือกอื่นคือการใช้มุมมองที่มีการจัดทำดัชนีด้วยคอลัมน์ที่แปลงเป็นวันที่และเวลาเพื่อความเข้ากันได้ อย่างไรก็ตามคุณจะต้องสามารถชี้แอปไปยังมุมมองได้
TamusJRoyce

9
การสนับสนุนเขตเวลาด้วย DATETIMEOFFSET เป็นตัวเรียกชื่อผิด มันจะเก็บออฟเซ็ต UTC เฉพาะเวลาที่เจาะจงทันทีไม่ใช่เขตเวลา
Suncat2000

6
@Porad: อะไรคือประโยชน์ในทางปฏิบัติของการเป็น "" พกพามากขึ้น "เนื่องจากเป็น" มาตรฐาน SQL "นั่นคือนอกจากทำให้คุณเขียนรหัสมากขึ้นอย่างมีนัยสำคัญที่น้อยกว่าอ่าน / บำรุงรักษาสำหรับ" พอร์ต "เพื่อ RDBMS อื่นที่ ไม่น่าจะเกิดขึ้นได้ตลอดอายุการใช้งานของรหัสนั้นนอกจากเครื่องมือ SQL Server และไดร์เวอร์ที่ Microsoft จัดเตรียมให้ Microsoft (ถ้ามี) จะมีแอพใดที่ใช้การแทนระดับบิตเฉพาะของDateTime2Type (หรือ SQL Server อื่น ๆ ) พิมพ์สำหรับเรื่องนั้น) ดูข้อเสียในคำตอบ 7/10/17 ด้านล่างว่าทำไมฉันถึงถาม
Tom

2
@ Adam Porad: นอกจากนี้ผลประโยชน์ทั้งหมดนั้นไม่จำเป็น (นอกวิศวกรรมหรือแอปพลิเคชันทางวิทยาศาสตร์) และดังนั้นจึงไม่คุ้มค่ากับการสูญเสียผลประโยชน์มากจำเป็นต้องมากขึ้น: ความสามารถที่ง่ายกว่า ค่าตัวเลขทศนิยม (# of days รวมถ้า appl., วันที่เป็นเศษส่วนตั้งแต่นาทีวันที่เวลา) สำหรับการบวก, การลบ, ขั้นต่ำ, สูงสุดและค่าเฉลี่ย ดูข้อเสียในคำตอบ 7/10/17 ด้านล่างของฉันสำหรับรายละเอียด
ทอม

493

DATETIME2มีช่วงวันที่เป็น "0001/01/01" ถึง " DATETIME9999/12/31 " ในขณะที่ประเภทสนับสนุนเฉพาะปี 1753-9999

นอกจากนี้หากคุณต้องการDATETIME2สามารถแม่นยำมากขึ้นในแง่ของเวลา; DATETIME ถูก จำกัด ไว้ที่ 3 1/3 มิลลิวินาทีในขณะที่DATETIME2สามารถแม่นยำได้ถึง 100ns

ทั้งสองประเภทจับคู่กับSystem.DateTimeใน. NET - ไม่แตกต่างกัน

หากคุณมีทางเลือกฉันจะแนะนำให้ใช้DATETIME2ทุกครั้งที่ทำได้ ฉันไม่เห็นประโยชน์ใด ๆ ที่ใช้DATETIME(ยกเว้นความเข้ากันได้แบบย้อนหลัง) - คุณจะมีปัญหาน้อยลง (เนื่องจากวันที่อยู่นอกช่วงและยุ่งยากเช่นนั้น)

บวก: หากคุณต้องการเพียงวันที่ (ไม่มีเวลา) ให้ใช้วันที่ - มันก็ดีDATETIME2และประหยัดพื้นที่เช่นกัน! :-) กันไปสำหรับครั้งเดียว - TIMEการใช้งาน นั่นคือสิ่งที่ประเภทเหล่านี้มีไว้สำหรับ!


158
ระวังเมื่อเพิ่มค่า. NET DateTime เป็นพารามิเตอร์ใน SqlCommand เพราะมันชอบที่จะสมมติว่ามันเป็นประเภท datetime เก่าและคุณจะได้รับข้อผิดพลาดถ้าคุณพยายามเขียนค่า DateTime ที่อยู่นอกช่วงปี 1753-9999 ยกเว้นว่าคุณระบุชนิดเป็น System.Data.SqlDbType.DateTime2 อย่างชัดเจนสำหรับ SqlParameter อย่างไรก็ตาม datetime2 นั้นยอดเยี่ยมเพราะสามารถเก็บค่าใด ๆ ที่สามารถเก็บไว้ในประเภท. NET DateTime
Triynko

10
@marc_s - นั่นไม่ใช่สิ่งที่มีประโยชน์สำหรับ?
JohnFx

8
@JohnFX ช้าไปนิดหน่อยที่นี่ - แต่คุณจะไม่ตั้ง datetime เป็นโมฆะ คุณจะใช้ Nullable <datetime> หรือ datetime หรือไม่ ซึ่งจัดการ null ได้ดี - และในการทำแผนที่กับ proc ก็จะทำ param.value = someDateTime ?? DBValue.Null โชคร้ายที่เรากำลังติดกับประเภทข้อมูลที่มีจำนวนหลังจากที่มัน - ก็ดูเหมือนว่าดังนั้น 'ทั่วไป':)
อดัม Tuliper - MSFT

69
ฮ่า ๆ ฉันแค่พยายามโหวตความคิดเห็นของตัวเอง (ด้านบน) ก่อนที่ฉันจะรู้ว่ามันเป็นความคิดเห็นของฉันเอง (ทำไว้เมื่อปีที่แล้ว) ฉันยังคงจัดการกับการตัดสินใจการออกแบบที่โง่เง่าของ. NET ในการตัดทอนค่า DateTime ทั้งหมดโดยค่าเริ่มต้นเมื่อส่งผ่านเป็น SqlParameters เว้นแต่คุณจะตั้งค่าเป็น SqlDbType.DateTime2 ที่แม่นยำยิ่งขึ้น มากสำหรับการอนุมานประเภทที่ถูกต้องโดยอัตโนมัติ จริง ๆ แล้วพวกเขาควรทำการเปลี่ยนแปลงที่โปร่งใสแทนที่การใช้งานที่มีความแม่นยำน้อยกว่ามีประสิทธิภาพน้อยกว่า จำกัด และยังคงชื่อเดิมของ "datetime" ไว้ โปรดดูstackoverflow.com/q/8421332/88409
Triynko

5
@marc_s ไม่ได้Nullable<DateTime>มีไว้เพื่ออะไร
ChrisW

207

datetime2ชนะในด้านส่วนใหญ่ยกเว้น (ความเข้ากันได้ของแอปเก่า)

  1. ขนาดใหญ่ช่วงของค่า
  2. แม่นยำยิ่งขึ้น
  3. พื้นที่เก็บข้อมูลขนาดเล็ก (หากระบุความแม่นยำที่ผู้ใช้ระบุ)

SQL ชนิดข้อมูลวันที่และเวลาเปรียบเทียบ - วันที่และเวลา, วันที่และเวลา 2, วันที่, เวลา

โปรดทราบประเด็นต่อไปนี้

  • วากยสัมพันธ์
    • datetime2 [(ความแม่นยำวินาทีเศษส่วน => ดูด้านล่างขนาดการจัดเก็บข้อมูล)]
  • ความแม่นยำระดับ
    • 0 ถึง 7 หลักด้วยความแม่นยำ 100ns
    • ความแม่นยำเริ่มต้นคือ 7 หลัก
  • ขนาดการจัดเก็บ
    • 6 ไบต์เพื่อความแม่นยำน้อยกว่า 3
    • 7 ไบต์เพื่อความแม่นยำ 3 และ 4
    • ความแม่นยำอื่น ๆ ทั้งหมดต้อง 8 ไบต์
  • DateTime2 (3)มีจำนวนหลักเท่ากับ DateTime แต่ใช้พื้นที่เก็บข้อมูล 7 ไบต์แทน 8 ไบต์ ( SQLHINTS- DateTime Vs DateTime2 )
  • ค้นหาเพิ่มเติมเกี่ยวกับdatetime2 (บทความ Transact-SQL MSDN)

แหล่งที่มาของรูปภาพ: ชุดการฝึกอบรม Self-Paced MCTS (ตรวจสอบ 70-432): Microsoft® SQL Server® 2008 - การติดตั้งและบำรุงรักษา บทที่ 3: ตาราง -> บทที่ 1: การสร้างตาราง -> หน้า 66


7
ขอบคุณที่แสดงสถิติ +1 สำหรับมันมันยอดเยี่ยมdatetime2มาก (ผู้ชนะ)
Pankaj Parkar

2
@Iman Abidi: ตามความคิดเห็นของ Oskar Berggren ลงวันที่ 10 กันยายน 2014 เวลา 15:51 น. ในบทความ "SQLHINTS- DateTime Vs DateTime2" ที่คุณอ้างอิง: "datetime2 (3) ไม่เหมือนกับ datetime พวกเขาจะมีหมายเลขเดียวกัน ตัวเลข แต่ความแม่นยำของวันที่และเวลาคือ 3.33 มิลลิวินาทีในขณะที่ความแม่นยำของวันที่และเวลา 2 (3) คือ 1 มิลลิวินาที "
Tom

1
@PanajParkar: ว้าวไม่เร็วขนาดนั้น คุณอาจต้องการดูส่วนข้อเสียของคำตอบของฉันลงวันที่ 7/10/17 ด้านล่าง
Tom

การdatetime2ใช้พื้นที่เก็บข้อมูลน้อยลงกว่าdatetimeแต่ยังมีช่วงกว้างและแม่นยำยิ่งขึ้นได้อย่างไร
ได

107

ฉันเห็นด้วยกับ @marc_s และ @Adam_Poward - DateTime2 เป็นวิธีที่ต้องการไปข้างหน้า มีช่วงกว้างของวันที่มีความแม่นยำสูงขึ้นและใช้พื้นที่เก็บข้อมูลที่เท่ากันหรือน้อยกว่า (ขึ้นอยู่กับความแม่นยำ)

สิ่งหนึ่งที่การอภิปรายพลาด แต่ ...
@Marc_s ฯBoth types map to System.DateTime in .NET - no difference there: สิ่งนี้ถูกต้องแต่สิ่งที่ตรงกันข้ามนั้นไม่เป็นความจริง ... และสำคัญเมื่อทำการค้นหาช่วงวันที่ (เช่น "ค้นหาระเบียนทั้งหมดที่แก้ไขเมื่อวันที่ 5/5/2010")

รุ่น .NET ของ มีช่วงที่คล้ายกันและมีความแม่นยำในการDatetime DateTime2เมื่อการทำแผนที่สุทธิDatetimeลงไปที่ SQL เก่าปัดเศษนัยเกิดขึ้น SQL เก่านั้นมีความแม่นยำถึง 3 มิลลิวินาที ซึ่งหมายความว่าใกล้เคียงที่สุดเท่าที่จะทำได้ในตอนท้ายของวัน ทุกอย่างที่สูงขึ้นจะถูกปัดขึ้นเป็นวันรุ่งขึ้นDateTimeDateTime11:59:59.997

ลองสิ่งนี้:

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

การหลีกเลี่ยงการปัดเศษโดยนัยนี้เป็นเหตุผลสำคัญที่จะย้ายไป DateTime2 การปัดเศษวันที่โดยนัยทำให้เกิดความสับสนอย่างชัดเจน:


14
คุณยังสามารถหลีกเลี่ยงการปัดเศษโดยไม่พยายามค้นหา "จุดจบ" ของวัน > = 5 พฤษภาคมและ <6 พฤษภาคมปลอดภัยยิ่งขึ้นและจะทำงานกับประเภทวันที่ / เวลาใด ๆ (ยกเว้นเวลาแน่นอน) นอกจากนี้ขอแนะนำให้หลีกเลี่ยงรูปแบบภูมิภาคที่คลุมเครือเช่น m / d / yyyy
Aaron Bertrand

2
@AaronBertrand - เห็นด้วยอย่างยิ่ง แต่เมื่อดูจำนวนคำถามเรามีเรื่องที่อธิบายได้คุ้มค่า
EBarr

1
คุณไม่เปลี่ยนจากทำไม20100505เพื่อ5/5/2010? รูปแบบเดิมจะทำงานกับภูมิภาคใด ๆ ใน SQL Server หลังจะพัง: SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')โอ๊ะโอ2015-07-01 00:00:00.000
ริค

1
@EBarr: Re "DateTime2 เป็นวิธีการที่ต้องการไปข้างหน้ามันมีช่วงกว้างของวันที่ความแม่นยำสูงขึ้นและใช้การจัดเก็บเท่ากันหรือน้อยกว่า (ขึ้นอยู่กับความแม่นยำ": ฉันไม่เห็นด้วยอย่างยิ่งดูส่วนข้อเสียของคำตอบลงวันที่ 7/10/17 ด้านล่าง ในระยะสั้นผลประโยชน์เหล่านั้นไม่จำเป็น (นอกวิศวกรรม / แอปทางวิทยาศาสตร์) และดังนั้นจึงไม่คุ้มค่ากับการสูญเสียผลประโยชน์ที่จำเป็นยิ่งมีความจำเป็นมากขึ้นความสามารถที่ง่ายกว่ามาก (แม้จะพิจารณาการแก้ไขปัญหา) เพื่อแปลง / # ของวันรวมถ้า appl., เศษส่วนตั้งแต่นาทีวันที่ - เวลา) ค่าสำหรับ +, - และเฉลี่ย
Tom

20

คำตอบและความคิดเห็นเกือบทั้งหมดมีข้อดีและข้อเสียอย่างหนัก นี่คือสรุปของข้อดีและข้อเสียทั้งหมดจนถึงบวกข้อเสียที่สำคัญบางอย่าง (ใน # 2 ด้านล่าง) ฉันเคยเห็นกล่าวถึงเพียงครั้งเดียวหรือไม่เลย

  1. ข้อดี:

1.1 เป็นไปตามมาตรฐาน ISO เพิ่มเติม (ISO 8601) (แม้ว่าฉันจะไม่รู้ว่าสิ่งนี้เกิดขึ้นได้อย่างไรในทางปฏิบัติ)

1.2 ช่วงเพิ่มเติม (1/1/0001 ถึง 12/31/9999 เทียบกับ 1/1 / 1753-12 / 31/9999) (แม้ว่าช่วงพิเศษช่วงก่อนปี 1753 จะไม่ถูกใช้ยกเว้นอดีต, ในแอพเชิงประวัติศาสตร์ดาราศาสตร์ธรณีวิทยาและอื่น ๆ )

1.3 ตรงกับช่วงของช่วงประเภท. NET DateTime(แม้ว่าทั้งคู่จะแปลงกลับไปกลับมาโดยไม่มีการเข้ารหัสพิเศษหากค่าอยู่ในช่วงของประเภทเป้าหมายและความแม่นยำยกเว้น Con # 2.1 ด้านล่างจะเกิดข้อผิดพลาด / การปัดเศษอื่น)

1.4 ความแม่นยำมากขึ้น (100 นาโนวินาทีหรือ 0.000,000,1 วินาทีเทียบกับ 3.33 มิลลิวินาทีหรือ 0.003,33 วินาที) (แม้ว่าความแม่นยำพิเศษจะไม่ถูกนำมาใช้ยกเว้นในอดีตในแอปด้านวิศวกรรม / วิทยาศาสตร์)

1.5 เมื่อกำหนดค่าสำหรับคล้ายกัน (ใน 1 มิลลิวินาทีไม่ "เหมือนกัน" (เช่นใน 3.33 มิลลิวินาที) ตามที่ Iman Abidi อ้างว่า) ความแม่นยำเป็นDateTimeใช้พื้นที่น้อยกว่า (7 กับ 8 ไบต์) แต่แน่นอนคุณจะสูญเสีย ผลประโยชน์ที่แม่นยำซึ่งน่าจะเป็นหนึ่งในสอง (ช่วงอื่น ๆ ที่เป็น) ส่วนใหญ่ touted แม้ว่าจะมีประโยชน์ที่ไม่จำเป็น)

  1. ข้อเสีย:

2.1 เมื่อผ่านพารามิเตอร์ไป .NET SqlCommandคุณต้องระบุSystem.Data.SqlDbType.DateTime2ถ้าคุณอาจจะผ่านค่านอก SQL Server DateTimeของช่วงและ / System.Data.SqlDbType.DateTimeหรือความแม่นยำเพราะเป็นค่าเริ่มต้น

2.2 ไม่สามารถแปลงโดยปริยาย / ง่าย ๆ ให้เป็นค่าตัวเลขทศนิยม (# ของวันตั้งแต่นาทีวันที่เวลา) เพื่อทำสิ่งต่อไปนี้กับ / ในการแสดงออกของ SQL Server โดยใช้ค่าตัวเลขและตัวดำเนินการ:

2.2.1 เพิ่มหรือลบจำนวนวันหรือบางส่วน หมายเหตุ: การใช้DateAddฟังก์ชั่นเป็นวิธีแก้ปัญหาไม่สำคัญเมื่อคุณต้องการพิจารณาหลาย ๆ อย่างหากไม่ใช่ทุกส่วนของวันที่

2.2.2 นำความแตกต่างระหว่างวันที่และเวลาสองครั้งเพื่อการคำนวณ“ อายุ” หมายเหตุ: คุณไม่สามารถใช้DateDiffฟังก์ชั่นของ SQL Server เพียงเพราะมันไม่ได้คำนวณageเป็นคนส่วนใหญ่คาดหวังว่าถ้าสองวันที่ - เวลาเกิดขึ้นเพื่อข้ามขอบเขตปฏิทิน / นาฬิกาวันที่และเวลาของหน่วยที่ระบุถ้าแม้แต่เศษส่วนเล็ก ๆ ของหน่วยนั้นมันจะคืนความแตกต่างเป็น 1 ของหน่วยนั้นเทียบกับ 0 ตัวอย่างเช่นDateDiffในDayวันที่สองครั้ง - เพียง 1 มิลลิวินาทีเท่านั้นที่แยกจากกันจะคืนค่า 1 เทียบกับ 0 (วัน) ถ้าวันที่เหล่านั้นเป็น ในวันตามปฏิทินต่างๆ (เช่น“ 1999-12-31 23: 59: 59.9999999” และ“ 2000-01-01 00: 00: 00.0000000”) 1 มิลลิวินาทีความแตกต่างวันที่ - เวลาเดียวกันหากย้ายเพื่อไม่ให้ข้ามวันปฏิทินจะคืน“ DateDiff” Dayเป็น 0 (วัน)

2.2.3 ใช้เวลาAvgวันครั้ง (ในรวม Query) โดยเพียงแค่การแปลงไป“ลอย” DateTimeครั้งแรกและจากนั้นกลับมาอีกครั้ง

หมายเหตุ: ในการแปลงDateTime2เป็นตัวเลขคุณต้องทำบางอย่างเช่นสูตรต่อไปนี้ซึ่งยังถือว่าค่าของคุณไม่น้อยกว่าปี 1970 (ซึ่งหมายความว่าคุณสูญเสียช่วงพิเศษทั้งหมดบวกอีก 217 ปีหมายเหตุ: คุณอาจ ไม่สามารถปรับสูตรเพื่อให้มีช่วงพิเศษได้เนื่องจากคุณอาจพบปัญหาการล้นของตัวเลข

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0- ที่มา:“ https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html

แน่นอนว่าคุณสามารถCastทำสิ่งDateTimeแรกได้ (และหากจำเป็นต้องกลับไปใช้DateTime2) แต่คุณจะสูญเสียความแม่นยำและช่วง (ทั้งหมดก่อนปี 1753) ของการDateTime2เทียบกับDateTimeซึ่งเป็น 2 ที่ใหญ่ที่สุดและในเวลาเดียวกัน prolly 2 ต้องการโอกาสที่น้อยที่สุดซึ่งทำให้เกิดคำถามว่าทำไมใช้เมื่อคุณสูญเสียการแปลงโดยปริยาย / ง่ายไปเป็นตัวเลขทศนิยม (# ของวัน) สำหรับการบวก / การลบ / "อายุ" (เทียบกับDateDiff) / Avgcalcs ซึ่งเป็นประโยชน์ จากประสบการณ์ของฉัน

Btw, Avgวันที่ - เวลาเป็น (หรืออย่างน้อยควรจะเป็น) กรณีการใช้งานที่สำคัญ a) นอกจากใช้ในการรับช่วงเวลาเฉลี่ยเมื่อวันที่ - เวลา (เนื่องจากฐานวันที่ทั่วไปเวลา) ถูกใช้เพื่อแสดงระยะเวลา (การปฏิบัติทั่วไป), b) นอกจากนี้ยังมีประโยชน์ที่จะได้รับสถิติประเภทแดชบอร์ดเกี่ยวกับวันที่เฉลี่ย - เวลาอยู่ในคอลัมน์วันที่ของช่วง / กลุ่มของแถว c) ad-hoc มาตรฐาน (หรืออย่างน้อยควรเป็นมาตรฐาน) เพื่อตรวจสอบ / แก้ไขปัญหาค่าในคอลัมน์ที่อาจไม่ถูกต้องตลอดไป / และอีกต่อไปและ / หรืออาจจำเป็นต้องเลิกใช้คือการแสดงรายการสำหรับแต่ละค่าที่เกิดขึ้น และ (ถ้ามี) Min, AvgและMaxตราประทับวันเวลาที่เกี่ยวข้องกับค่าที่


1
เช่นมุมมองที่แตก - มันชี้ให้เห็นด้าน c # ของสมการ เมื่อรวมกับ "ข้อดี" อื่น ๆ ทั้งหมดมันจะช่วยให้ผู้คนเลือกได้ดีขึ้นอยู่กับว่าพวกเขาต้องการเจ็บปวดที่ไหน
EBarr

1
@EBarr: เฉพาะจุดด้อย # 1 ในมุมมองที่แตก "" ของฉัน "" ชี้ให้เห็นด้าน c # ของสมการ " ส่วนที่เหลือ (ข้อด้อยของ 2.2.1 - 2.2.3) ซึ่งอย่างที่ฉันบอกว่าเป็นประโยชน์ที่จำเป็นมาก (จากDateTime) ล้วนเกี่ยวข้องกับผลกระทบต่อ SQL Server Queries และข้อความสั่งต่างๆ
Tom

Re 2.2.1 - ถือว่าเป็นวิธีปฏิบัติที่ไม่ปลอดภัยในการคำนวณทางคณิตศาสตร์ในวันที่และวิธีที่ต้องการคือการใช้ DateAdd และฟังก์ชั่นที่เกี่ยวข้องเสมอ นี่คือวิธีปฏิบัติที่ดีที่สุด มีหนี้สินที่ร้ายแรงในการทำเลขคณิตวันที่ไม่ใช่อย่างน้อยก็คือมันไม่ทำงานสำหรับประเภทวันที่ส่วนใหญ่ ไม่กี่บทความ: sqlservercentral.com/blogs/... sqlblog.org/2011/09/20/...
RBerman

@Rerman: Re "ไม่ปลอดภัย": ไม่ปลอดภัยเฉพาะบางประเภทวันที่เท่านั้น (เช่นที่DateTime2ฉันพูดถึงไปแล้ว (เนื่องจากมีโอกาสล้นสูง) เรื่อง "ไม่ทำงานสำหรับประเภทวันที่ส่วนใหญ่": คุณต้องการใช้งานกับวันที่เท่านั้นและวันที่ส่วนใหญ่ในแอปส่วนใหญ่จะไม่จำเป็นต้องแปลงเป็นประเภทวันที่อื่นตลอดอายุการใช้งานของพวกเขา , DateTime2ไปDateTime(เช่นจะทำ "ทางคณิตศาสตร์ในวัน"; P) ระบุว่ามันไม่คุ้มค่าทุกพิเศษการเข้ารหัสในไม่โปรแกรมเพียง แต่ยัง Ad-hoc แบบสอบถามการวิจัยเพื่อใช้ไม่ใช่คณิตศาสตร์ประเภทวันที่เป็นมิตร..
ทอม

15

DateTime2 สร้างความเสียหายหากคุณเป็นนักพัฒนา Access ที่พยายามเขียน Now () ลงในฟิลด์ที่เป็นปัญหา เพิ่งทำการโยกย้าย Access -> SQL 2008 R2 และใส่เขตข้อมูลวันที่และเวลาเป็น DateTime2 ผนวกระเบียนด้วย Now () ตามค่าที่ระเบิดทิ้ง มันไม่เป็นไรเมื่อวันที่ 1/1/2012 2:53:04 PM แต่ไม่ใช่ในวันที่ 1/10/2012 2:53:04 PM

เมื่อตัวละครสร้างความแตกต่าง หวังว่าจะช่วยใครซักคน


15

นี่คือตัวอย่างที่จะแสดงความแตกต่างของขนาดหน่วยเก็บข้อมูล (ไบต์) และความแม่นยำระหว่าง smalldatetime, datetime, datetime2 (0), และ datetime2 (7):

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

ซึ่งผลตอบแทน

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

ดังนั้นถ้าฉันต้องการเก็บข้อมูลลงไปที่สอง - แต่ไม่ถึงมิลลิวินาที - ฉันสามารถบันทึก 2 ไบต์แต่ละถ้าฉันใช้ datetime2 (0) แทน datetime หรือ datetime2 (7)


10

ในขณะที่มีเพิ่มขึ้นความแม่นยำกับdatetime2ลูกค้าบางส่วนไม่สนับสนุนวัน , เวลาหรือdatetime2และบังคับให้คุณแปลงเป็นตัวอักษรสตริง Microsoft กล่าวถึง ODBC "ระดับล่าง", OLE DB, JDBC และ SqlClient โดยเฉพาะปัญหากับชนิดข้อมูลเหล่านี้และมีแผนภูมิแสดงวิธีที่แต่ละชนิดสามารถแมปชนิด

ถ้าค่าความเข้ากันได้มากกว่าความแม่นยำใช้วันที่และเวลา


10

คำถามเก่า ... แต่ฉันต้องการเพิ่มบางสิ่งบางอย่างที่ไม่ได้ระบุไว้โดยใครที่นี่ ... (หมายเหตุ: นี่คือการสังเกตของฉันเองดังนั้นอย่าขออ้างอิงใด ๆ )

Datetime2 เร็วขึ้นเมื่อใช้ในเกณฑ์ตัวกรอง

TLDR:

ใน SQL 2016 ฉันมีตารางที่มีหนึ่งแสนแถวและคอลัมน์ datetime ENTRY_TIME เพราะมันจำเป็นในการจัดเก็บเวลาที่แน่นอนถึงวินาที ในขณะที่ดำเนินการค้นหาที่ซับซ้อนที่มีการรวมจำนวนมากและแบบสอบถามย่อยเมื่อฉันใช้ที่ข้อเป็น:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

แบบสอบถามเริ่มต้นได้ดีเมื่อมีหลายร้อยแถว แต่เมื่อจำนวนแถวเพิ่มขึ้นแบบสอบถามเริ่มให้ข้อผิดพลาดนี้:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

ฉันลบส่วนคำสั่ง where และโดยไม่คาดคิดแบบสอบถามถูกเรียกใช้ใน 1 วินาทีแม้ว่าตอนนี้แถวทั้งหมดสำหรับวันที่ทั้งหมดจะถูกดึงออกมา ฉันเรียกใช้เคียวรีด้านในโดยที่มีส่วนคำสั่งและใช้เวลา 85 วินาทีและไม่มีส่วนคำสั่งที่ใช้เวลา 0.01 วินาที

ฉันเจอหลายหัวข้อที่นี่สำหรับปัญหานี้ในการกรองวันที่และเวลา

ฉันปรับการค้นหาสักเล็กน้อย แต่ความเร็วที่แท้จริงที่ฉันได้รับคือการเปลี่ยนคอลัมน์วันที่และเวลาเป็นวันที่ 2

ตอนนี้แบบสอบถามเดียวกันที่หมดเวลาก่อนหน้านี้ใช้เวลาน้อยกว่าหนึ่งวินาที

ไชโย


9

การตีความสตริงวันที่เข้าdatetimeและdatetime2อาจแตกต่างกันเมื่อใช้DATEFORMATการตั้งค่าที่ไม่ใช่ของสหรัฐอเมริกา เช่น

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

ผลตอบแทนนี้2013-05-06(เช่น 6 พฤษภาคม) สำหรับdatetimeและ2013-06-05(เช่น 5 มิถุนายน) datetime2สำหรับ แต่ด้วยการdateformatกำหนดให้mdyทั้งสอง@dและผลตอบแทน@d22013-06-05

datetimeพฤติกรรมดูเหมือนว่าที่ขัดแย้งกับเอกสาร MSDNของSET DATEFORMATรัฐที่: บางรูปแบบสตริงตัวอักษรเช่น ISO 8601, จะถูกตีความเป็นอิสระจากการตั้งค่า เห็นได้ชัดว่าไม่เป็นความจริง!

จนกว่าฉันจะถูกกัดฉันคิดเสมอว่าyyyy-mm-ddวันที่จะได้รับการจัดการอย่างถูกต้องโดยไม่คำนึงถึงการตั้งค่าภาษา / สถานที่


2
Nope สำหรับ ISO 8601 ฉันคิดว่าคุณหมายถึง YYYYMMDD (ไม่มีขีดกลาง) SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;ลองอีกครั้งด้วยเครื่องหมายขีดกลาง
Aaron Bertrand

1
มาตรฐานอนุญาตให้ใช้ทั้งรูปแบบ YYYY-MM-DD และ YYYYMMDD สำหรับการแสดงวันที่ในปฏิทิน ฉันคิดว่า MSDN ควรมีความเฉพาะเจาะจงมากขึ้นเกี่ยวกับชุดย่อยของข้อกำหนด ISO 8601 ที่ถูกตีความอย่างอิสระ!
Richard Fawcett

1
ฉันรู้ว่า แต่ใน SQL Server เท่านั้นไวยากรณ์ไม่รีบปลอดภัย
Aaron Bertrand

6

ตามบทความนี้หากคุณต้องการให้ DateTime มีความแม่นยำเหมือนกันโดยใช้ DateTime2 คุณเพียงแค่ใช้ DateTime2 (3) สิ่งนี้ควรให้ความแม่นยำเท่ากันใช้เวลาน้อยกว่าหนึ่งไบต์และให้ช่วงที่ขยายเพิ่ม


เพื่อความชัดเจนมันมีความแม่นยำเช่นเดียวกับ SQL datetime ไม่ใช่. NET DateTime
Sam Rueby

ถูกต้องฉันคิดว่าทุกคนจะเข้าใจบริบท แต่ความคุ้มค่าที่ระบุไว้โดยเฉพาะ
jKlaus

4

ฉันเพิ่งเจอประโยชน์อย่างใดอย่างหนึ่งมากขึ้นสำหรับDATETIME2มันหลีกเลี่ยงข้อผิดพลาดในหลามadodbapiโมดูลซึ่งพัดขึ้นถ้าห้องสมุดมาตรฐานdatetimeค่าผ่านซึ่งมีไม่ใช่ศูนย์ microseconds สำหรับDATETIMEคอลัมน์ DATETIME2แต่ทำงานได้ดีถ้าคอลัมน์ถูกกำหนดให้เป็น


0
Select ValidUntil + 1
from Documents

SQL ด้านบนจะไม่ทำงานกับเขตข้อมูล DateTime2 จะส่งคืนและข้อผิดพลาด "ตัวดำเนินการชนิดที่ขัดแย้งกัน: datetime2 ไม่เข้ากันกับ int"

การเพิ่ม 1 เพื่อรับในวันถัดไปเป็นสิ่งที่นักพัฒนาทำกับวันที่หลายปี ขณะนี้ Microsoft มีเขตข้อมูล datetime2 ใหม่ที่ไม่สามารถจัดการฟังก์ชันการทำงานอย่างง่ายนี้ได้

"ลองใช้รูปแบบใหม่ที่แย่กว่าเดิม" ฉันไม่คิดอย่างนั้น!


2
เพียงแค่เราชัดเจนที่นี่datetimeและdatetime2ทั้งสองชนิดข้อมูลถูกนำมาใช้ใน SQL Server 2008 นอกจากนี้คุณยังได้รับOperand type clash: date is incompatible with intจากdateประเภทที่มีมาตั้งแต่จุดวัน ทั้งสามประเภทข้อมูลใช้งานได้ดีกับdateadd(dd, 1, ...)แม้ว่า
AlwaysLearning

2
ยังไม่ชัดเจน ฉันมีฐานข้อมูล SQLServer 2005 พร้อมเขตข้อมูลวันที่และเวลา
Paul McCarthy

0

ผมคิดว่าDATETIME2เป็นวิธีที่ดีกว่าที่จะเก็บเพราะมันมีประสิทธิภาพมากขึ้นกว่าdate DATETIMEในSQL Server 2008คุณสามารถใช้DATETIME2มันเก็บวันที่และเวลาจะใช้เวลา 6-8 ในการจัดเก็บและมีความแม่นยำของbytes ดังนั้นใครก็ตามที่ต้องการความแม่นยำมากขึ้นเวลาที่จะต้องการ100 nanosecondsDATETIME2

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.