เกี่ยวกับวันที่ของฐานข้อมูลประเภท crusade: ถูกต้อง? คุ้มค่า? มีใครรู้สึกบ้างไหม?


13

ฉันใช้เวลามากในการตอบคำถาม SQL ผ่านทาง SO ฉันเจอคำถามของตระกูลนี้บ่อยครั้ง:

SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'

SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'

SELECT * FROM person WHERE birthdate BETWEEN 'some string' AND 'other string'

เช่นอาศัยการแปลงโดยนัยจากสตริงถึงวันที่ (ไม่ดี) ของพารามิเตอร์ที่กำหนดหรืออาศัยฐานข้อมูลที่แปลงค่า x ล้านแถวของฐานข้อมูลเป็นสตริงและทำการเปรียบเทียบสตริง (แย่กว่า)

ฉันแสดงความคิดเห็นเป็นครั้งคราวโดยเฉพาะอย่างยิ่งถ้าเป็นผู้ใช้ตัวแทนสูงที่เขียนคำตอบสมาร์ท แต่คนที่ฉันรู้สึกว่าควรจะมีความเลอะเทอะน้อยลง / พิมพ์ด้วยชนิดข้อมูลของพวกเขาน้อยลง

ความคิดเห็นมักจะใช้แบบฟอร์มที่มันอาจจะดีกว่าถ้าพวกเขาแปลงสตริงเป็นวันที่อย่างชัดเจนโดยใช้ to_date (Oracle), str_to_date (MySQL), แปลง (SQLSERVER) หรือกลไกที่คล้ายกัน:

    --oracle
    SELECT * FROM person WHERE birthdate BETWEEN TO_DATE('20170101', 'YYYYMMDD') AND TO_DATE('20170301', 'YYYYMMDD')

    --mysql
    SELECT * FROM person WHERE birthdate BETWEEN STR_TO_DATE('20170101', '%Y%m%d') AND STR_TO_DATE('20170301', '%Y%m%d')

    --SQLS, ugh; magic numbers
    SELECT * FROM person WHERE birthdate BETWEEN CONVERT(datetime, '20170101', 112) AND CONVERT(datetime, '20170301', 112)

เหตุผลทางเทคนิคของฉันสำหรับการทำเช่นนั้นก็คือมันชัดเจนว่าเป็นรูปแบบของวันที่และให้แน่ใจว่าพารามิเตอร์แหล่งที่มาไม่กี่กลายเป็นประเภทข้อมูลของคอลัมน์เป้าหมาย สิ่งนี้จะป้องกันความเป็นไปได้ใด ๆ ที่ฐานข้อมูลจะได้รับการแปลงโดยปริยายที่ไม่ถูกต้อง (อาร์กิวเมนต์วันที่ 3 มกราคม / 1 มีนาคมของตัวอย่างแรก) และป้องกันการตัดสินใจที่จะแปลงค่าวันที่นับล้านในตารางเป็นสตริง การจัดรูปแบบที่อาจไม่ตรงกับรูปแบบของวันที่ในพารามิเตอร์สตริงภายใน sql) เพื่อทำการเปรียบเทียบ - horrors abound

เหตุผลทางสังคม / วิชาการของฉันสำหรับการทำเช่นนั้นคือ SO เป็นเว็บไซต์การเรียนรู้ ผู้คนที่อยู่ในนั้นจะได้รับความรู้ไม่ว่าโดยนัยหรือโดยชัดแจ้ง ในการเข้าสู่มือใหม่ด้วยคำค้นหานี้เป็นคำตอบ:

SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'

อาจทำให้พวกเขาคิดว่าสิ่งนี้มีเหตุผลปรับวันที่สำหรับรูปแบบที่ต้องการ:

SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'

หากอย่างน้อยพวกเขาเห็นความพยายามที่ชัดเจนในการแปลงวันที่พวกเขาอาจเริ่มทำมันสำหรับรูปแบบวันที่แปลก ๆ ของพวกเขาและฆ่าแมลงตลอดกาลบางอย่างก่อนที่จะเกิดขึ้น ท้ายที่สุดเรา (I) ลองและห้ามไม่ให้ผู้คนเข้าสู่พฤติกรรมการฉีด SQL (และใครก็ตามที่สนับสนุนการตั้งค่าการสืบค้นแล้วประกาศให้คนขับรถที่@pBirthdateเป็นสตริงเมื่อส่วนหน้ามีประเภทวันที่และเวลา?

กลับไปที่สิ่งที่เกิดขึ้นหลังจากที่ฉันแนะนำ: ฉันมักจะได้รับ pushback บางอย่างเพื่อ "ชัดเจน, ใช้ x" คำแนะนำเช่น "คนอื่นทำมัน", "มันใช้ได้สำหรับฉันเสมอ", "แสดงคู่มือหรือเอกสารอ้างอิงให้ฉัน ที่บอกว่าฉันควรจะชัดเจน "หรือ" อะไร "

ฉันถามว่าในการตอบสนองต่อสิ่งเหล่านี้ไม่ว่าพวกเขาจะค้นหาคอลัมน์ int หรือไม่โดยการWHERE age = '99'ผ่านอายุเป็นสตริง "ไม่ต้องงี่เง่าเราไม่จำเป็นต้องใส่" เมื่อค้นหา int "เป็นการตอบสนองดังนั้นจึงมีความซาบซึ้งใจต่อประเภทข้อมูลที่แตกต่างกันในใจบางแห่ง แต่บางทีก็อาจจะไม่เกี่ยวข้องกับโลจิคัลกระโดดที่ค้นหา int คอลัมน์โดยการส่งผ่านสตริง (เห็นได้ชัดว่าโง่) และการค้นหาคอลัมน์วันที่โดยการส่งผ่านสตริง

ดังนั้นใน SQLs ของเราเรามีวิธีเขียนสิ่งต่าง ๆ เป็นตัวเลข (ใช้ตัวเลขโดยไม่มีตัวคั่น) สิ่งต่าง ๆ เป็นสตริงสตริง (ใช้อะไรก็ได้ระหว่างตัวคั่นเครื่องหมายวรรคตอน) .. ทำไมไม่มีตัวคั่นสำหรับวันที่ มันเป็นประเภทข้อมูลพื้นฐานในฐานข้อมูลส่วนใหญ่หรือไม่ สิ่งทั้งหมดนี้อาจจะแก้ไขได้เพียงแค่มีวิธีการเขียนวันที่ในลักษณะเดียวกับจาวาสคริปต์ที่ให้เราระบุ regex โดยการใส่/ด้านข้างของอักขระบางตัว /Hello\s+world/. ทำไมไม่มีอะไรเป็นเดท

ตามความรู้ของฉัน (เฉพาะ) Microsoft Access มีสัญลักษณ์ที่ระบุว่า "วันที่เขียนระหว่างตัวคั่นเหล่านี้" เพื่อให้เราได้รับทางลัดที่ดีเช่นWHERE datecolumn = #somedate#แต่การนำเสนอวันที่ยังคงมีปัญหาเช่น mm / di vs dd / mm เนื่องจาก MS เล่นอย่างรวดเร็วและหลวมกับสิ่งที่ฝูงชน VB คิดว่าเป็นความคิดที่ดี


กลับไปที่ประเด็นหลัก: ฉันเถียงว่ามันเป็นการฉลาดที่จะมีความชัดเจนกับสื่อนี้ที่บังคับให้เราผ่านประเภทข้อมูลที่หลากหลายเป็นสตริง ..

มันเป็นการยืนยันที่ถูกต้อง?

ฉันควรทำสงครามครูเสดต่อไปไหม? เป็นจุดที่ถูกต้องหรือไม่ที่การพิมพ์อย่างเข้มงวดเป็นโมเดิร์นไม่เลย? หรือ RDBMS ทุกอัน (รวมถึงเวอร์ชั่นโบราณ) จะออกมาที่นั่นหรือไม่เมื่อมีการผลักข้อความค้นหาให้WHERE datecolumn = 'string value'แปลงสตริงเป็นวันที่อย่างถูกต้องและทำการค้นหาโดยไม่ต้องแปลงข้อมูลตาราง / สูญเสียการใช้ดัชนี? ฉันสงสัยว่าอย่างน้อยที่สุดก็จากประสบการณ์ส่วนตัวของ Oracle 9 ฉันสงสัยว่าอาจมีบางสถานการณ์ที่ต้องออกไปหากมีการเขียนสตริงในรูปแบบมาตรฐาน ISO อยู่เสมอและคอลัมน์ก็เป็นบางวันที่แล้ว พารามิเตอร์สตริงจะถูกแปลงโดยปริยายอย่างถูกต้องเสมอ สิ่งนี้ทำให้ถูกต้องหรือไม่

มันเป็นงานที่คุ้มค่าหรือไม่?

หลายคนดูเหมือนจะไม่ได้รับมันหรือไม่สนใจหรือแสดงความเจ้าเล่ห์ในการที่ ints ของพวกเขาเป็น ints แต่วันที่ของพวกเขาเป็นสตริง .. ร่วมกันมากที่สุดแม้ว่าจะเป็นที่ไม่กี่คนที่เคยหันกลับมาและกล่าวว่า "คุณรู้ อะไรฉันเห็นด้วยกับจุดของคุณฉันจะชัดเจนเกี่ยวกับวันที่ของฉันจากนี้ไป "


ฉันเคยเห็นใครบางคนที่มีปัญหากับWHERE datecolumn = 01/02 / 12'` ที่เป็นไปได้ที่พวกเขาจะขอปี 1912, 2012, 2001, 1901, 12 หรือ 1 นอกจากนี้ยังมีปัญหานอกโลกฐานข้อมูลจำนวน ของโปรแกรมเมอร์ที่ไม่สามารถเข้าใจว่าทำไมการแปลง"09"เป็น int ที่เป็นสาเหตุของความผิดพลาดเป็นพยุหะ9 ไม่ได้เป็นฐานแปดหลักที่ถูกต้องและเป็นผู้นำ 0 ทำให้ฐานแปดสตริงในจำนวนมากของระบบ
สตีฟบาร์นส์

2
ฉันคิดเกี่ยวกับการขยายตัวอย่างของฉันเพื่อถามว่าWHERE age = '0x0F'เป็นวิธีที่ถูกต้องในการหวังว่าฐานข้อมูลจะค้นหาเด็กอายุสิบห้าปีหรือไม่
Caius Jard

1
ฉันลบคำถามที่ไม่ได้อยู่ที่นี่ - เราไม่ได้ทำตามคำขอทรัพยากร หนึ่งใน 2 คะแนนโหวตปิดได้รับด้วยเหตุผลนี้ มิฉะนั้นฉันคิดว่านี่เป็นคำถามที่ถูกต้องแม้ว่ามันอาจจะเป็นขอบที่กว้างเกินไป ฉันหวังว่าการลบคำถามนอกหัวข้อจะช่วยให้สิ่งต่าง ๆ แคบลงเล็กน้อย
Thomas Owens

TL; DR แต่ในระบบการผลิตฉันคาดว่าวันที่เช่นนี้จะอยู่ในพารามิเตอร์เกือบตลอดเวลา การเข้ารหัสวันที่ลงในคิวรีเป็นปัญหาที่ใหญ่กว่าว่าคุณใช้การแปลงโดยนัยหรือไม่ หากฉันกำลังเขียนแบบสอบถามแบบใช้ครั้งเดียวก็อาจใช้ได้หรือไม่ก็ได้ ฉันไม่เคยทำสิ่งนี้เลย (เพราะฉันจำวันที่เริ่มต้นรูปแบบไม่ได้) แต่ฉันไม่แน่ใจว่ามันสำคัญมาก
JimmyJames

1
ชีวิตคือการเลือกการต่อสู้ของคุณ ในมุมมองของฉันคนนี้ก็ไม่คุ้มค่าการต่อสู้ ...
ร็อบบี้ดี

คำตอบ:


7

คุณเขียน:

พารามิเตอร์เหล่านั้นคือ 1 มกราคมถึง 3 มกราคมหรือ 1 มีนาคม

นั่นเป็นแหล่งที่มาของข้อผิดพลาด การชี้เรื่องนี้ไปยังผู้ถามอาจเป็นประโยชน์กับผู้อ่านรายอื่นดังนั้นใช่นี่เป็นข้อกังวลที่ถูกต้อง อย่างไรก็ตามเพื่อที่จะสร้างสรรค์ฉันจะ

  • อ้างถึง ANSI SQL และใช้ตัวอักษร DATE หรือ DATETIME จากมาตรฐานนั้น

  • ใช้รูปแบบวันที่และเวลาปกติที่ไม่แน่นอนของ DBMS เฉพาะ (และพูดถึงภาษา SQL ที่ใช้)

น่าเสียดายที่ไม่ใช่ทุก ๆ DBMS ที่สนับสนุนตัวอักษรวันที่ ANSI SQL ในลักษณะที่คล้ายกัน (ถ้าพวกเขาสนับสนุนเลย) ดังนั้นโดยทั่วไปสิ่งนี้จะนำไปสู่ความแตกต่างของวิธีการที่สอง ความจริง "มาตรฐาน" ไม่ได้นำมาใช้อย่างเข้มงวดโดยผู้ขายฐานข้อมูลที่แตกต่างกันอาจเป็นส่วนหนึ่งของปัญหาที่นี่

หมายเหตุเพิ่มเติมสำหรับระบบในโลกแห่งความเป็นจริงหลาย ๆ คนผู้คนสามารถพึ่งพาตำแหน่งที่ตั้งเฉพาะที่แน่นอนบนเซิร์ฟเวอร์ฐานข้อมูลแม้ว่าแอปพลิเคชันไคลเอนต์จะถูกแปลเป็นภาษาท้องถิ่นเพราะมีเซิร์ฟเวอร์เพียงชนิดเดียวเท่านั้นที่กำหนดค่าด้วยวิธีเดียวกัน ดังนั้น '01 / 03/2017 'สามารถสันนิษฐานได้ว่ามีรูปแบบคงที่' dd / mm / yyyy 'หรือ' mm / dd / yyyy 'สำหรับ SQL ใด ๆ ที่ใช้กับระบบเฉพาะที่ทำงานด้วย ดังนั้นถ้าใครบอกคุณ "ก็มักจะทำงานสำหรับฉัน" นี้อาจจะย่อมเป็นคำตอบที่เหมาะสมสำหรับสภาพแวดล้อมของเขา หากเป็นกรณีนี้มันจะคุ้มค่าที่จะพูดคุยเรื่องนี้น้อยลง

พูดคุยเกี่ยวกับ "เหตุผลด้านประสิทธิภาพ": ตราบใดที่ไม่มีปัญหาประสิทธิภาพที่วัดได้นี่เป็นเรื่องที่เชื่อโชคลางมากในเรื่อง "ปัญหาประสิทธิภาพที่อาจเกิดขึ้น" หากฐานข้อมูลกำลังทำการแปลงแบบสตริงต่อวันเป็นล้าน ๆ ครั้งหรือไม่น่าจะไม่สำคัญว่าเมื่อเวลาต่างกันเพียง 1/1000 วินาทีและคอขวดจริงคือเครือข่ายที่ทำให้การสืบค้นเป็น 10 วินาทีล่าสุด ดังนั้นควรคำนึงถึงเรื่องเหล่านี้ให้ดีกว่าตราบใดที่มีคนถามอย่างชัดเจนถึงข้อควรพิจารณาด้านประสิทธิภาพ

ฉันควรทำสงครามครูเสดต่อไปไหม?

ฉันบอกความลับกับคุณ: ฉันเกลียดสงครามศาสนา พวกเขาไม่ได้นำไปสู่สิ่งที่มีประโยชน์ ดังนั้นหากรายละเอียดวันที่ / เวลาที่ไม่น่าไว้วางใจใน SQL อาจนำไปสู่ปัญหาพูดถึงพวกเขา แต่อย่าพยายามบังคับคนให้เข้มงวดมากขึ้นหากไม่ได้นำประโยชน์มาให้พวกเขาในบริบทปัจจุบันของพวกเขา


นี่ไม่ใช่คำถามเกี่ยวกับความคลุมเครือของรูปแบบวันที่อเมริกัน vs Sensible มันเกี่ยวกับว่ามันมีเหตุผลหรือไม่ที่จะส่งผ่านวันที่ในคำสั่ง SQL เป็นสตริงและพึ่งพาการแปลงเป็นวันที่โดยนัย คำถามของฐานข้อมูลที่ต้องทำหนึ่งล้าน date-> str การแปลงสำหรับทุกล้านแถวเป็นหนึ่งในแง่มุมของประสิทธิภาพและมันอาจใช้เวลา 1 / 1,000th ของวินาทีสำหรับหนึ่งแบบสอบถาม แต่ตอนนี้จินตนาการในบริบทของความสอดคล้องกัน ผู้ใช้ ปัญหาประสิทธิภาพการทำงานที่ใหญ่กว่าคือการแปลงข้อมูลหมายความว่าดัชนีจะไม่สามารถใช้งานได้อีกต่อไปซึ่งอาจร้ายแรงมาก
Caius Jard

@CaiusJard: คำตอบของฉันหมายถึง: บางครั้งมันก็สมเหตุสมผลและบางครั้งก็ไม่ขึ้นอยู่กับบริบท และอย่างสุจริตฉันปฏิเสธที่จะ"... ลองนึกภาพ ... "อะไรก็ได้ที่นี่ เมื่อพูดถึงประสิทธิภาพการพูดคุยถึงกรณีสมมุติใด ๆ ก็ไม่มีประโยชน์ เมื่อมีปัญหาประสิทธิภาพที่วัดได้แล้วมันเป็นเวลาที่จะปรับให้เหมาะสมและบางครั้งก็เพื่อปรับให้เหมาะสมแบบไมโครไม่ได้มาก่อน
Doc Brown

มันน่าสนใจที่คุณเห็นว่ามันเป็นสมมุติ; ผมเห็นการพึ่งพาพฤติกรรมส่อเป็นโอกาสที่ชัดเจนสำหรับข้อบกพร่องและภาวะแทรกซ้อนที่ผลการดำเนินงานที่จะเกิดขึ้น (ด้วยเหตุผลเอกสารดี: ดัชนีจะไม่ได้ทำงานถ้าข้อมูลคอลัมน์ทั้งหมดจะถูกเปลี่ยนก่อนที่จะมีการสืบค้น) และมีคำแนะนำอย่างชัดเจนเหล่านี้ไม่สามารถเกิดขึ้น
Caius Jard

@CaiusJard: อย่าเล่นกับคำ - ด้วย "สมมติฐาน" ฉันไม่ได้หมายถึง "ไม่น่าเป็นไปได้" ฉันใช้คำศัพท์สำหรับสถานการณ์จินตนาการทุกประเภทซึ่งตรงข้ามกับ "สถานการณ์ที่มีอยู่จริง" ซึ่งสามารถวัดสิ่งที่เกิดขึ้นได้
Doc Brown

1
@CaiusJard: ถ้าคุณต้องการสร้างความประทับใจให้กับมืออาชีพในอุตสาหกรรมอื่น ๆ คุณควรรู้ว่าทำไม "การเพิ่มประสิทธิภาพ" แตกต่างจาก "การเพิ่มประสิทธิภาพความปลอดภัย" และนั่นคือจุดของฉันที่นี่ - ปัญหาด้านประสิทธิภาพสามารถจัดการได้หลังจากที่พวกเขาเกิดขึ้น สายเกินไป. ปัญหาด้านความปลอดภัยไม่ควรหลีกเลี่ยงก่อนที่จะเกิดขึ้น ดังนั้นโปรดอย่าเปรียบเทียบแอปเปิ้ลกับส้ม ถ้าคุณชอบสงครามครูเสดข้อโต้แย้งการรักษาความปลอดภัยที่ดีมากเหมาะสำหรับการนี้ ;-)
หมอสีน้ำตาล

5

สงครามครูเสดของคุณไม่ได้แก้ปัญหา

มีสองประเด็นที่แยกจากกัน:

  • การแปลงชนิดโดยนัยใน SQL

  • รูปแบบวันที่ที่ไม่ชัดเจนเช่น 05/06/07

ฉันเห็นว่าคุณมาจากไหนด้วยสงครามครูเสดของคุณ แต่ฉันไม่คิดว่าการแปลงที่ชัดเจนจะช่วยแก้ปัญหาได้จริง:

  • การแปลงโดยนัยยังคงเกิดขึ้นในกรณีที่มีความไม่ตรงกันระหว่างประเภทในการเปรียบเทียบ หากเปรียบเทียบสตริงกับวันที่ SQL จะพยายามแปลงสตริงเป็นวันที่ก่อน ดังนั้นการเปรียบเทียบคอลัมน์ประเภทวันที่กับค่าวันที่แปลงอย่างชัดเจนจึงเหมือนกับการเปรียบเทียบกับวันที่ในรูปแบบสตริง ความแตกต่างเพียงอย่างเดียวที่ฉันเห็นคือถ้าคุณเปรียบเทียบค่าวันที่กับคอลัมน์ที่ไม่ได้มีวันที่ แต่เป็นสตริง - แต่นี่จะเป็นข้อผิดพลาดในทุกกรณี

  • การใช้การแปลงที่ชัดเจนไม่ได้แก้ปัญหาความกำกวมในรูปแบบวันที่ที่ไม่ใช่ ISO

ทางออกเดียวที่ฉันเห็น:

  • อย่าเปรียบเทียบคอลัมน์ประเภทสตริงกับค่าที่ไม่ใช่สตริง
  • ใช้รูปแบบวันที่ประเภท ISO เท่านั้น

และแน่นอนว่าอย่าเก็บวันที่ไว้ในคอลัมน์ประเภทสตริง แต่อีกครั้งการแปลงตัวอักษรวันที่อย่างชัดเจนจะไม่ป้องกันสิ่งนี้

การแปลงโดยนัยเป็นข้อผิดพลาดใน SQL แต่เนื่องจากวิธีการออกแบบภาษาฉันไม่เห็นประโยชน์ของการแปลงที่ชัดเจน มันจะไม่หลีกเลี่ยงการแปลงโดยนัยและจะทำให้โค้ดอ่านและเขียนได้ยากขึ้น


จริง บางทีฉันควรชี้ให้เห็นจากมุมมองนี้ว่าสิ่งที่เหมาะสมที่สุดที่จะทำคือให้แน่ใจว่าตัวถูกดำเนินการด้านข้อมูลและตัวถูกดำเนินการตามตัวอักษรมีประเภทข้อมูลเดียวกัน (ไม่ว่าจะเป็นสตริงวันที่หรืออะไรก็ตาม) ฉันไม่เฉพาะให้คำแนะนำนี้เฉพาะในคำถามที่ฉันรู้คอลัมน์ตารางเป็น DATETIME และคำตอบของพวกเขาตัวอย่างเช่นใช้ตัวถูกดำเนินการสตริงกับการแปลงโดยปริยาย ..
Caius Jard

คำตอบนี้มีบางอย่างไม่ถูกต้อง คุณทำคะแนนที่น่าสนใจ แต่ฉันรู้สึกว่าข้อสรุปนั้นเป็นอุดมคติ จากมุมมองการออกแบบใช่รูปแบบวันที่ที่ไม่ใช่ ISO ชัดเจนต่อสายตามนุษย์ แต่หากใช้การแปลงอย่างชัดเจน syntactically จะไม่ชัดเจนกับตัวแยกวิเคราะห์ ในทำนองเดียวกันกระบวนการ ETL จำนวนมากที่เกี่ยวข้องกับวันที่จะต้องมีการเปรียบเทียบบางอย่าง (ในรูปแบบของการนำเข้าไฟล์) ของสตริงกับรูปแบบวันที่ของฐานข้อมูล การพยายามกำจัดการเปรียบเทียบสตริงกับวันที่ดูเหมือนไม่สมจริงสำหรับฉัน
DanK

@DANK: ETL เป็นปัญหาที่แตกต่าง - ถ้าคุณกำลังอ่านข้อมูลจากไฟล์ CSV หรือบางสิ่งบางอย่างแน่นอนคุณต้องประมวลผลข้อมูลเป็นสตริงและแจงเป็นค่าที่พิมพ์ไว้อย่างชัดเจน แต่นั่นไม่ใช่สถานการณ์ที่ OP อธิบายไว้
JacquesB

อาจเป็นจุดที่ฉันอธิบายได้อย่างง่ายดาย ไม่มีอะไรพิเศษเกี่ยวกับสตริงของตัวเลขที่จัดเก็บใน csv ที่ต้องการประกาศรูปแบบอย่างชัดเจนเมื่อทำการแยกวิเคราะห์และมันเกี่ยวข้องกับการโต้เถียงที่ฉันทำหากมือใหม่อ่านคำตอบบางอย่างในที่ที่มือโปรไม่ได้พยายามอย่างชัดเจน ประกาศรูปแบบวันที่นำมือใหม่มาคิดว่าพวกเขาไม่ต้องกังวลเกี่ยวกับมัน (หรือว่า db จะแยกวิเคราะห์มันอย่างถูกต้องตลอดเวลา)
Caius Jard

@CaiusJard: ฉันเชื่อว่าสิ่งเหล่านี้เป็นสถานการณ์ที่แตกต่างกันมาก เมื่อพูดถึง SQL ในสถานการณ์ปกติฉันถือว่าคอลัมน์มีประเภทที่เหมาะสมเช่นคอลัมน์จำนวนเต็มเป็นประเภทจำนวนเต็มคอลัมน์วันที่เป็นประเภทข้อมูลและอื่น ๆ หากคุณไม่มีประเภทที่ถูกต้องในตาราง (เช่นวันที่ร้านค้าเป็นสตริง) คุณกำลังมีปัญหาอย่างลึกซึ้งและการแปลงตัวอักษรวันที่อย่างชัดเจนในแบบสอบถามจะไม่บันทึกคุณซึ่งเป็นจุดของฉัน
JacquesB

3

ก่อนอื่นคุณมีประเด็น ไม่ควรใส่วันที่ลงในสตริง เอ็นจิ้นฐานข้อมูลเป็นสัตว์ที่ซับซ้อนซึ่งคุณจะไม่แน่ใจ 100% ว่าจะเกิดอะไรขึ้นภายใต้ประทุนหากมีการสอบถามโดยพลการ การแปลงวันที่ทำให้สิ่งต่าง ๆ ชัดเจนและสามารถเพิ่มประสิทธิภาพได้

แต่

มันไม่ใช่ปัญหาที่ควรค่ากับความพยายามพิเศษในการแก้ปัญหาสำหรับคนส่วนใหญ่ ถ้ามันง่ายต่อการใช้ตัวอักษรวันที่ในแบบสอบถามมันจะง่ายต่อการปกป้องตำแหน่งของคุณ แต่มันไม่ใช่ ฉันใช้ SQL Server เป็นส่วนใหญ่ดังนั้นพยายามจดจำว่าการแปลงวันที่ไม่เกิดขึ้น

สำหรับคนส่วนใหญ่ประสิทธิภาพที่เพิ่มขึ้นนั้นเล็กน้อย "ทำไมใช่ Mr. Boss-man ฉันใช้เวลาเพิ่มอีก 10 นาทีในการแก้ไขข้อผิดพลาดแบบง่าย (ฉันต้อง google วิธีแปลงวันที่เพราะไวยากรณ์นั้นคือ ... พิเศษ ... ) แต่ฉันบันทึกเพิ่มอีก 0.00001 วินาทีใน แบบสอบถามที่ถูกเรียกใช้งานบ่อยครั้ง " นั่นจะไม่บินไปสถานที่ส่วนใหญ่ที่ฉันเคยทำงาน

แต่จะลบความคลุมเครือในรูปแบบวันที่ที่คุณพูด อีกครั้งสำหรับแอปพลิเคชันจำนวนมาก (แอปพลิเคชันภายใน บริษัท สิ่งที่รัฐบาลท้องถิ่น ฯลฯ ฯลฯ ) ไม่ใช่เรื่องที่น่ากังวล และสำหรับแอพพลิเคชั่นที่เป็นข้อกังวล (แอพพลิเคชั่นขนาดใหญ่ระดับสากลหรือระดับองค์กร) นั่นอาจกลายเป็นความกังวลของ UI / ชั้นธุรกิจหรือ บริษัท เหล่านั้นมีทีมงาน DBA ที่มีความรอบรู้ TL / DR: หากการทำให้เป็นสากลเป็นปัญหาใครบางคนกำลังคิดถึงมันอยู่และได้ทำไปแล้วตามที่คุณแนะนำ (หรือช่วยลดปัญหา)

แล้วตอนนี้ล่ะ?

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


1

ฉันเถียงว่าเป็นการดีที่จะมีความชัดเจนกับสื่อนี้ที่บังคับให้เราผ่านประเภทข้อมูลที่หลากหลายเป็นสตริง

สมมติว่า "วันที่" ถูกส่งผ่านไปรอบ ๆ "ใน" สตริงแล้วใช่; ฉันยอมรับอย่างแน่นอนว่าคุณมีสิทธิ์ที่จะทำเช่นนี้

เมื่อใดที่ "01/04/07"
* 4 มกราคม
* วันที่ 1 เมษายน
* 7 เมษายน [2001]?

สิ่งเหล่านี้หรือทั้งหมดอาจถูกต้องขึ้นอยู่กับว่า "คอมพิวเตอร์" เลือกตีความมันอย่างไร

หากคุณต้องสร้าง SQL แบบไดนามิกโดยใช้ตัวอักษรดังนั้นการจัดรูปแบบวันที่ของคุณจะต้องมีการกำหนดอย่างดีและโดยเฉพาะอย่างยิ่งเครื่องจักรที่ไม่เกี่ยวข้อง (ฉันมีหนึ่งแปลกบน Windows Server ที่การประมวลผลตามวันที่ภายในบริการ Windows เนื่องจากโอเปอเรเตอร์เข้าสู่คอนโซลที่มีการกำหนดรูปแบบวันที่แตกต่างกัน!) โดยส่วนตัวฉันใช้ [d] รูปแบบ "yyyy-mm-dd" โดยเฉพาะ

อย่างไรก็ตาม ...

ที่ดีที่สุดของการแก้ปัญหาคือการใช้ parameterised แบบสอบถามซึ่งบังคับให้ชนิดของข้อมูลที่จะแปลงก่อน SQL ได้รับการมีส่วนร่วม - รับ "วันที่" คุ้มค่าเป็นวันที่กองกำลังพารามิเตอร์แปลงชนิดในช่วงต้น (ทำให้หมดจดปัญหาการเข้ารหัสไม่ได้เป็น SQL เดียว) .


ฉันเห็นด้วยถึงแม้ว่าปัญหาเดียวกันสามารถถูกบังคับอีกครั้งกับการค้นหาแบบกำหนดพารามิเตอร์โดยทำWHERE datecolumn = @dateParameterแล้วในรหัสส่วนหน้าการบอกไดรเวอร์ DB ว่า@dateParameterเป็นประเภท varchar และติด"01/04/07"อยู่กับมัน แรงบันดาลใจดั้งเดิมสำหรับคำถามของฉันคือฉันสงสัยว่าทุกคนที่จะบอกฉันว่าฉันคลั่งไคล้ในการทำแบบสอบถามแบบพารามิเตอร์แล้วในลมหายใจเดียวกันให้หนึ่งบรรทัดดังนั้นคำตอบที่ดูเหมือนWHERE datecol = 'some string that looks like a date'(และคาดว่ามือใหม่ควรรู้ มันเป็นเพียงคำแนะนำ / parameterize มันเพื่อหลีกเลี่ยงปัญหา)
Caius Jard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.