Oracle DateTime trong mệnh đề Where?


84

Tôi có sql một cái gì đó như thế này:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED >= TO_DATE('26/JAN/2011','dd/mon/yyyy')

-> Điều này trả về 10 hàng và TIME_CREATED = '26 -JAN-2011 '

Bây giờ khi tôi làm điều này, tôi không nhận được bất kỳ hàng nào trở lại,

SELECT EMP_NAME, DEPT
    FROM EMPLOYEE
    WHERE TIME_CREATED = TO_DATE('26/JAN/2011','dd/mon/yyyy')

-> Took to hơn out

Bất kỳ lý do tại sao?


4
Bạn nên tránh các định dạng ngày phụ thuộc vào ngôn ngữ. Điều đó có thể gây ra sự cố trên các hệ thống khác nhau. Bạn nên sử dụng 01thay vì JAN(tất nhiên là cộng với định dạng phê duyệt) để đảm bảo mã của bạn chạy mà không gặp sự cố trên bất kỳ hệ thống nào.
a_horse_with_no_name

Câu trả lời:


149

Có: TIME_CREATED chứa ngày và giờ . Sử dụng TRUNCđể rút ngắn thời gian:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TRUNC(TIME_CREATED) = TO_DATE('26/JAN/2011','dd/mon/yyyy')

CẬP NHẬT:
Như Dave Costa đã chỉ ra trong nhận xét bên dưới, điều này sẽ ngăn Oracle sử dụng chỉ mục của cột TIME_CREATEDnếu nó tồn tại. Một cách tiếp cận thay thế không có vấn đề này là:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED >= TO_DATE('26/JAN/2011','dd/mon/yyyy') 
      AND TIME_CREATED < TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1

14
Lưu ý rằng phương pháp này sẽ ngăn việc sử dụng chỉ mục trên TIME_CREATED, nếu có.
Dave Costa

Cảm ơn bạn đã đăng giải pháp. Nó nhanh chóng và dễ dàng tìm thấy. Mặc dù tôi đã làm việc trên các DBMS khác như Ingres, MS-SQL, MS-Access và DB2, tôi chưa làm việc với Oracle trước nhiệm vụ hiện tại của mình.
Jason TEPOORTEN 19/10/12

Tại sao không sử dụng BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1?
ajeh

2
@ajeh: Tôi không thích betweenvì sự mơ hồ. Nghe có vẻ như thể nó là giới hạn độc quyền trong khi thực tế nó là bao gồm. Đó là lý do tại sao tôi tránh nó. Hơn nữa, trong ví dụ cụ thể này, nó sẽ không giống nhau.
Daniel Hilgarth

28

Bạn cũng có thể sử dụng phần sau để bao gồm phần TIME trong truy vấn của mình:

SELECT EMP_NAME
     , DEPT
  FROM EMPLOYEE 
 WHERE TIME_CREATED >= TO_DATE('26/JAN/2011 00:00:00', 'dd/mon/yyyy HH24:MI:SS');

8

Bạn cũng có thể làm:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TRUNC(TIME_CREATED) = DATE '2011-01-26'

7

Điều này là do một DATEcột trong Oracle cũng chứa một phần thời gian. Kết quả của to_date()hàm là một ngày với thời gian được đặt thành 00:00:00và do đó nó có thể không khớp với bất kỳ hàng nào trong bảng.

Bạn nên sử dụng:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE trunc(TIME_CREATED) = TO_DATE('26/JAN/2011','dd/mon/yyyy')

5

Như những người khác đã nhận xét ở trên, việc sử dụng TRUNC sẽ ngăn chặn việc sử dụng các chỉ mục (nếu có một chỉ mục vào TIME_CREATED). Để tránh vấn đề đó, truy vấn có thể được cấu trúc như

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') 
            AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + INTERVAL '86399' second;

86399 ít hơn 1 giây so với số giây trong một ngày.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.