Saya menghabiskan banyak waktu menjawab pertanyaan SQL pada SO. Saya sering menemukan pertanyaan sejenis ini:
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'
yaitu baik mengandalkan konversi implisit dari string ke tanggal (buruk), dari parameter yang diberikan atau mengandalkan pada basis data yang mengonversi x juta nilai baris basis data ke string dan melakukan perbandingan string (lebih buruk)
Saya kadang-kadang membuat komentar, terutama jika itu adalah pengguna rep tinggi yang menulis jawaban cerdas, tetapi yang saya rasa benar-benar harus menjadi kurang ceroboh / diketik ketat dengan tipe data mereka
Komentar biasanya mengambil bentuk yang mungkin akan lebih baik jika mereka secara eksplisit mengkonversi string mereka ke tanggal, menggunakan to_date (Oracle), str_to_date (MySQL), convert (SQLSERVER) atau mekanisme serupa:
--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)
Justifikasi teknis saya untuk melakukan ini adalah bahwa itu eksplisit mengenai format tanggal, dan memastikan bahwa beberapa parameter sumber pasti menjadi tipe data dari kolom target. Ini mencegah segala kemungkinan bahwa database akan mendapatkan konversi implisit yang salah (argumen 3 Januari / 1 Maret dari contoh pertama) dan mencegah db memutuskan untuk mengonversi jutaan nilai tanggal dalam tabel menjadi string (menggunakan beberapa tanggal khusus server pemformatan yang bahkan mungkin tidak cocok dengan format tanggal dalam parameter string dalam sql) untuk melakukan perbandingan - kengerian berlimpah
Pembenaran sosial / akademis saya untuk melakukan itu adalah bahwa SO adalah situs pembelajaran; orang-orang di dalamnya memperoleh pengetahuan baik secara implisit atau eksplisit. Memukul pemula dengan pertanyaan ini sebagai jawaban:
SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'
Mungkin membuat mereka berpikir ini masuk akal, menyesuaikan tanggal untuk beberapa format yang mereka sukai:
SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'
Jika mereka setidaknya melihat beberapa upaya eksplisit untuk mengkonversi tanggal, mereka mungkin mulai melakukannya untuk format tanggal aneh mereka, dan membunuh beberapa bug selamanya sebelum mereka muncul. Setelah semua, kami (saya) mencoba dan mencegah orang untuk masuk ke kebiasaan injeksi SQL (dan apakah ada yang akan mengadvokasi parameterisasi permintaan dan kemudian menyatakan kepada driver yang @pBirthdate
merupakan string, ketika frontend memiliki tipe datetime?)
Kembali ke apa yang terjadi setelah saya membuat rekomendasi saya: Saya biasanya mendapatkan beberapa pushback ke rekomendasi "menjadi eksplisit, gunakan x", seperti "semua orang melakukannya", "selalu bekerja untuk saya", "tunjukkan kepada saya beberapa dokumen manual atau referensi yang mengatakan saya harus eksplisit "atau bahkan" apa ?? "
Saya telah bertanya, dalam menanggapi beberapa di antaranya, apakah mereka akan mencari kolom int dengan melakukan WHERE age = '99'
melewati usia sebagai string. "Jangan konyol, kita tidak perlu menempatkan 'ketika mencari int" datang jawabannya, jadi ada beberapa penghargaan untuk tipe data yang berbeda di pikiran mereka di suatu tempat, tapi mungkin tidak ada koneksi ke lompatan logis yang mencari sebuah int kolom dengan melewatkan string (tampaknya konyol) dan mencari kolom tanggal dengan melewatkan string (tampaknya masuk akal) adalah kemunafikan
Jadi dalam SQL kami, kami memiliki cara untuk menulis sesuatu sebagai angka (menggunakan angka, tanpa pembatas), hal-hal sebagai string string (menggunakan apa pun di antara pembatas apostrof). Mengapa tidak ada pembatas untuk tanggal? Ini adalah tipe data fundamental dalam kebanyakan DB? Mungkinkah semua ini bisa diselesaikan hanya dengan memiliki cara menulis tanggal dengan cara yang sama javascript memungkinkan kita menentukan regex dengan menempatkan /
kedua sisi beberapa karakter. /Hello\s+world/
. Mengapa tidak punya sesuatu untuk kencan?
Sebenarnya, sepengetahuan saya, (hanya) Microsoft Access sebenarnya memiliki simbol yang menunjukkan "tanggal telah ditulis di antara pembatas ini" sehingga kita bisa mendapatkan jalan pintas yang baik seperti WHERE datecolumn = #somedate#
tetapi presentasi tanggal masih bertanggung jawab untuk memberikan masalah misalnya mm / di vs dd / mm, karena MS selalu bermain cepat dan longgar dengan hal-hal yang dianggap kerumunan VB adalah ide yang bagus
Kembali ke poin utama: Saya berpendapat bahwa adalah bijaksana untuk secara eksplisit dengan media ini yang memaksa kita untuk melewati banyak tipe data yang berbeda sebagai string ..
Apakah ini pernyataan yang valid?
Haruskah saya melanjutkan perang salib ini? Apakah ini poin yang valid bahwa pengetikan ketat adalah modern tidak-tidak? Atau akankah setiap RDBMS (termasuk versi kuno) di luar sana, ketika mendorong kueri WHERE datecolumn = 'string value'
benar-benar pasti mengubah string ke tanggal dan melakukan pencarian tanpa mengkonversi data tabel / kehilangan penggunaan indeks? Saya curiga tidak, setidaknya dari pengalaman pribadi Oracle 9. Saya menduga juga bahwa mungkin ada beberapa skenario "get-away-with-it" jika string selalu ditulis dalam beberapa format standar ISO, dan kolom adalah beberapa rasa tanggal, maka parameter string akan selalu dikonversi dengan benar secara implisit. Apakah ini benar?
Apakah ini tugas yang berharga?
Banyak orang tampaknya tidak mendapatkannya, atau tidak peduli, atau menunjukkan kemunafikan karena int mereka adalah int tetapi kencan mereka adalah string. Namun yang paling umum adalah bahwa beberapa orang pernah berbalik dan berkata "Anda tahu apa, saya setuju dengan poin Anda. Saya akan secara eksplisit tentang tanggal saya mulai sekarang ".
WHERE age = '0x0F'
ada cara yang valid untuk berharap database akan mencari anak berusia lima belas tahun ..
WHERE datecolumn =
01/02/12 di mana mungkin mereka meminta untuk tahun 1912, 2012, 2001, 1901, 12 atau 1. Ini juga merupakan masalah di luar dunia basis data, nomor pemrogram yang tidak dapat memahami mengapa konversi"09"
ke int menyebabkan crash sangat banyak, 9 bukan digit oktal yang valid dan 0 terkemuka membuat string oktal dalam banyak sistem