Giả sử LAST_TRANSACTION_DATE
là DATE
cột (hoặc TIMESTAMP
) thì cả hai phiên bản đều rất tệ.
Trong cả hai trường hợp, DATE
cột sẽ được chuyển đổi hoàn toàn thành một ký tự chữ dựa trên cài đặt NLS hiện tại. Điều đó có nghĩa là với những khách hàng khác nhau, bạn sẽ nhận được những kết quả khác nhau.
Khi sử dụng các ký tự ngày luôn luôn sử dụng to_date()
với (!) một mặt nạ định dạng hoặc sử dụng một ký tự ngày ANSI. Bằng cách đó, bạn so sánh ngày với ngày không phải chuỗi với chuỗi. Vì vậy, để so sánh bình đẳng, bạn nên sử dụng:
LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')
Lưu ý rằng việc sử dụng 'MON' vẫn có thể dẫn đến lỗi với các cài đặt NLS khác nhau ('DEC'
so với 'DEZ'
hoặc 'MAR'
so với 'MRZ'
). Việc sử dụng số tháng (và năm có bốn chữ số) sẽ ít bị lỗi hơn nhiều:
LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')
hoặc sử dụng ký tự ngày ANSI
LAST_TRANSACTION_DATE = DATE '2007-07-30'
Bây giờ, lý do tại sao truy vấn trên rất có thể không trả về gì là trong Oracle DATE
các cột cũng bao gồm cả thời gian. Các ký tự ngày ở trên ẩn chứa thời gian 00:00
. Nếu thời gian trong bảng khác (ví dụ:19:54
) thì tất nhiên ngày tháng không bằng nhau.
Để giải quyết vấn đề này, bạn có các tùy chọn khác nhau:
- sử dụng
trunc()
trên cột của bảng để "chuẩn hóa" thời gian thành00:00
trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30
Tuy nhiên, điều này sẽ ngăn việc sử dụng chỉ mục được xác định vàoLAST_TRANSACTION_DATE
- sử dụng
between
LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')
Sự cố hiệu suất của giải pháp đầu tiên có thể được khắc phục bằng cách tạo chỉ mục vào trunc(LAST_TRANSACTION_DATE)
có thể được sử dụng bởi biểu thức đó. Nhưng biểu thức LAST_TRANSACTION_DATE = '30-JUL-07'
cũng ngăn chặn việc sử dụng chỉ mục vì nó được xử lý nội bộ dưới dạng to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'
Những điều quan trọng cần nhớ:
- Đừng bao giờ dựa vào chuyển đổi kiểu dữ liệu ngầm định. Nó sẽ cung cấp cho bạn vấn đề tại một số điểm. Luôn so sánh các loại dữ liệu chính xác
- Oracle
DATE
cột luôn chứa thời gian là một phần của quy tắc so sánh.