Tôi dành nhiều thời gian để trả lời các câu hỏi SQL trên SO. Tôi thường xuyên bắt gặp các truy vấn của ilk này:
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'
tức là dựa vào chuyển đổi ngầm định từ chuỗi sang ngày (xấu), của các tham số đã cho hoặc dựa vào cơ sở dữ liệu chuyển đổi x triệu giá trị hàng cơ sở dữ liệu thành chuỗi và thực hiện so sánh chuỗi (tệ hơn)
Thỉnh thoảng tôi đưa ra nhận xét, đặc biệt nếu đó là người dùng đại diện cao, người viết câu trả lời thông minh, nhưng người mà tôi cảm thấy thực sự nên bớt cẩu thả / xâu chuỗi với kiểu dữ liệu của họ
Nhận xét thường có dạng sẽ tốt hơn nếu họ chuyển đổi rõ ràng chuỗi của họ thành ngày, sử dụng to_date (Oracle), str_to_date (MySQL), convert (SQLSERVER) hoặc một số cơ chế tương tự:
--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)
Các biện minh kỹ thuật của tôi để làm như vậy là nó rõ ràng về định dạng của ngày và đảm bảo rằng một vài tham số nguồn chắc chắn trở thành kiểu dữ liệu của cột mục tiêu. Điều này ngăn bất kỳ khả năng nào cơ sở dữ liệu sẽ nhận được một chuyển đổi ngầm định (đối số thứ 3/1 tháng 3 của ví dụ đầu tiên) và nó ngăn db quyết định chuyển đổi một triệu giá trị ngày trong bảng thành chuỗi (sử dụng một số ngày cụ thể của máy chủ định dạng thậm chí có thể không khớp với định dạng của ngày trong các tham số chuỗi trong sql) để thực hiện so sánh - rất nhiều điều kinh khủng
Sự biện minh xã hội / học thuật của tôi để làm như vậy là SO là một trang web học tập; những người trên đó tiếp thu kiến thức hoặc ngầm hoặc rõ ràng. Để đánh một người mới với truy vấn này như một câu trả lời:
SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'
Có thể khiến họ nghĩ rằng điều này là hợp lý, điều chỉnh ngày cho một số định dạng họ thích:
SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'
Nếu ít nhất họ thấy một số nỗ lực rõ ràng để chuyển đổi ngày, họ có thể bắt đầu thực hiện nó cho định dạng ngày kỳ lạ của mình và tiêu diệt một số lỗi mãi mãi trước khi chúng phát sinh. Rốt cuộc, chúng tôi (tôi) cố gắng ngăn cản mọi người tập thói quen tiêm SQL (và có ai ủng hộ việc tham số hóa truy vấn và sau đó khai báo cho trình điều khiển đó @pBirthdate
là một chuỗi, khi giao diện có kiểu thời gian không?)
Quay lại những gì xảy ra sau khi tôi đưa ra khuyến nghị: Tôi thường nhận được một số phản hồi cho đề xuất "rõ ràng, sử dụng x", như "mọi người khác làm điều đó", "nó luôn hoạt động với tôi", "hiển thị cho tôi một số tài liệu tham khảo hoặc tài liệu tham khảo điều đó nói rằng tôi nên rõ ràng "hoặc thậm chí" những gì ?? "
Tôi đã hỏi, để trả lời một số trong số này, liệu họ có tìm kiếm một cột int hay không bằng cách WHERE age = '99'
vượt qua tuổi như một chuỗi. "Đừng ngớ ngẩn, chúng ta không cần phải đặt 'khi tìm kiếm int", vì vậy có một sự đánh giá cao cho các loại dữ liệu khác nhau trong tâm trí của họ ở đâu đó, nhưng có lẽ không có kết nối nào với bước nhảy vọt logic khi tìm kiếm một int cột bằng cách chuyển một chuỗi (có vẻ ngớ ngẩn) và tìm kiếm cột ngày bằng cách chuyển một chuỗi (có vẻ hợp lý) là đạo đức giả
Vì vậy, trong các SQL của chúng ta, chúng ta có một cách để viết các thứ dưới dạng số (sử dụng số, không có dấu phân cách), mọi thứ dưới dạng chuỗi chuỗi (sử dụng bất cứ thứ gì giữa các dấu phân cách dấu nháy đơn) .. Tại sao không có dấu phân cách cho ngày? Đó là một kiểu dữ liệu cơ bản trong hầu hết DB? Có thể giải quyết toàn bộ vấn đề này chỉ bằng cách viết một ngày theo cùng một cách javascript cho phép chúng tôi chỉ định một biểu thức chính bằng cách đặt /
một trong hai bên của một số ký tự. /Hello\s+world/
. Tại sao không có một cái gì đó cho ngày?
Trên thực tế, theo hiểu biết của tôi, (chỉ) Microsoft Access thực sự có các ký hiệu cho biết "một ngày đã được viết giữa các dấu phân cách này" để chúng tôi có thể có một lối tắt tốt như WHERE datecolumn = #somedate#
nhưng trình bày ngày vẫn có thể đưa ra các vấn đề, ví dụ như mm / di vs dd / mm, bởi vì MS luôn chơi nhanh và lỏng lẻo với những thứ mà đám đông VB nghĩ là một ý tưởng tốt
Quay lại điểm chính: Tôi cho rằng thật khôn ngoan khi nói rõ với phương tiện này buộc chúng ta phải vượt qua vô số kiểu dữ liệu khác nhau dưới dạng chuỗi ..
Đó có phải là một khẳng định hợp lệ?
Tôi có nên tiếp tục cuộc thập tự chinh này? Đây có phải là một điểm hợp lệ mà việc gõ chuỗi là không hiện đại? Hoặc mọi RDBMS (bao gồm cả các phiên bản cổ đại) ngoài kia, khi đẩy một truy vấn WHERE datecolumn = 'string value'
hoàn toàn chắc chắn chuyển đổi chính xác chuỗi thành một ngày và thực hiện tìm kiếm mà không chuyển đổi dữ liệu bảng / mất sử dụng chỉ mục? Tôi nghi ngờ là không, ít nhất là từ kinh nghiệm cá nhân của Oracle 9. Tôi cũng nghi ngờ rằng có thể có một số tình huống xảy ra nếu các chuỗi luôn được viết theo định dạng tiêu chuẩn ISO và cột là một số hương vị ngày, sau đó tham số chuỗi sẽ luôn được chuyển đổi hoàn toàn chính xác. Điều này làm cho nó đúng?
Nó có phải là một nhiệm vụ đáng giá?
Nhiều người dường như không hiểu nó, hoặc không quan tâm, hoặc thể hiện một số giả thuyết ở chỗ ints của họ là ints nhưng ngày của họ là chuỗi .. Thông thường, hầu hết mọi người đều quay lại và nói "bạn biết không những gì, tôi đồng ý với quan điểm của bạn. Tôi sẽ nói rõ về ngày của tôi kể từ bây giờ ".
WHERE age = '0x0F'
là một cách hợp lệ để hy vọng cơ sở dữ liệu sẽ tìm kiếm những đứa trẻ mười lăm tuổi không ..
WHERE datecolumn =
01/02/12, nơi có thể họ đang yêu cầu cho năm 1912, 2012, 2001, 1901, 12 hoặc 1. Đây cũng là một vấn đề bên ngoài thế giới cơ sở dữ liệu, con số trong số các lập trình viên không thể hiểu tại sao chuyển đổi"09"
sang int gây ra sự cố là quân đoàn, 9 không phải là chữ số bát phân hợp lệ và số 0 đứng đầu tạo ra chuỗi bát phân trong rất nhiều hệ thống