2012-09-26 33 views
6

Tôi có một bảng với các lĩnh vực sau:Oracle: không phải là một tháng hợp lệ

Báo cáo (tên bảng) Rep_Date (ngày) Rep_Time (ngày)

Trường Rep_Time có giá trị như '01/01/1753 07:30:00 'tức là phần thời gian có liên quan. Tôi đã viết truy vấn sau:

select Reports.pid, MaxDate from Reports 
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY') 
     || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate 
    from reports 
    group by pid 
) ReportMaxDate 
on Reports.PID = ReportMaxDate.PID 
AND To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE 
WHERE REPORTS.PID=61 

Phần bảng dẫn xuất của truy vấn chạy, nhưng khi tôi chạy toàn bộ truy vấn tôi gặp lỗi: "không phải là tháng hợp lệ". Tại sao điều này?

Để giúp gỡ lỗi việc này; nếu tôi chạy truy vấn sau đây:

select rep_date, rep_time from reports where pid=61 and rownum=1 

tôi nhận được:

Rep_Date = 01/04/2009 
Rep_Time = 01/01/1753 13:00:00 

CẬP NHẬT 15:58 bây giờ tôi có thể thực hiện các truy vấn sau đây:

select Reports.pid, MaxDate from Reports 
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY') 
     || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate 
    from reports group by pid 
) ReportMaxDate 
on Reports.PID = ReportMaxDate.PID 
AND to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE 
WHERE REPORTS.PID=61 

Tuy nhiên, tôi cần thêm một câu lệnh nữa vào mệnh đề WHERE so sánh phần thời gian của MaxDate với rep_time: to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE không hoạt động.

Trả lời

21

1.

To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE 

đang gây ra vấn đề này. khi bạn sử dụng to_date mà không có định dạng thời gian, oracle sẽ sử dụng các định dạng NLS phiên hiện tại để chuyển đổi, trong trường hợp của bạn có thể không phải là "DD/MM/YYYY". Kiểm tra này ...

SQL> select sysdate from dual; 

SYSDATE 
--------- 
26-SEP-12 

Which means my session's setting is DD-Mon-YY 

SQL> select to_char(sysdate,'MM/DD/YYYY') from dual; 

TO_CHAR(SY 
---------- 
09/26/2012 


SQL> select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual; 
select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual 
       * 
ERROR at line 1: 
ORA-01843: not a valid month 

SQL> select to_date(to_char(sysdate,'MM/DD/YYYY'),'MM/DD/YYYY') from dual; 

TO_DATE(T 
--------- 
26-SEP-12 

2.

Quan trọng hơn, Tại sao các bạn chuyển đổi để char và sau đó đến nay, thay vì so sánh trực tiếp

MaxDate = REP_DATE 

Nếu bạn muốn bỏ qua thời gian thành phần trong MaxDate trước khi so sánh, bạn nên sử dụng ..

trunc(MaxDate) = rep_date 

thay thế.

== Cập nhật: dựa trên câu hỏi được cập nhật.

Rep_Date = 01/04/2009 Rep_Time = 01/01/1753 13:00:00 

Tôi nghĩ vấn đề phức tạp hơn. nếu rep_time được dự định là thời gian, thì bạn không thể lưu trữ nó trong cơ sở dữ liệu dưới dạng một ngày tháng. Nó sẽ phải là một chuỗi hoặc ngày để khoảng thời gian hoặc số lượng như giây (nhờ Alex, xem this). Nếu có thể, tôi sẽ đề nghị sử dụng một cột rep_date có cả ngày tháng và thời gian và so sánh nó với cột ngày tối đa trực tiếp.

Nếu đó là một hệ thống đang chạy và bạn không có quyền kiểm soát đối với việc trả tiền, bạn có thể thử điều này.

trunc(rep_date) = trunc(maxdate) and 
to_char(rep_date,'HH24:MI:SS') = to_char(maxdate,'HH24:MI:SS') 

Dù bằng cách nào, thời gian được lưu trữ không chính xác (như bạn có thể nói từ năm 1753) và có thể có các vấn đề khác về sau.

+0

Trong câu trả lời cho câu hỏi của bạn MaxDate là DateTime và REP_DATE là ngày. Trunc (MaxDate) = rep_date DO là gì? – w0051977

+0

trunc (ngày) sẽ loại bỏ thành phần thời gian (thực tế, nó làm cho thành phần thời gian bằng 0, đó là trường hợp có cột ngày tháng như REP_DATE. Không có điều nào như ngày tháng trong Oracle.) –

+0

+1, cảm ơn nó công trinh. Bạn có thể giải thích làm thế nào để có được thành phần thời gian của một datetime trước khi tôi chấp nhận? to_date (to_char (maxdate, 'HH24: MI: SS'), 'HH24: MI: SS') dường như không hoạt động. – w0051977

2

Để biết định dạng ngày hoạt động, hãy chèn bản ghi bằng cách sử dụng sysdate. bởi bạn có thể tìm thấy định dạng ngày hành động. ví dụ:

insert into emp values(7936,'Mac','clerk',7782,sysdate,1300,300,10); 

bây giờ, chọn bản ghi được chèn.

select ename,hiredate from emp where ename='Mac'; 

kết quả là

ENAME HIREDATE 
Mac  06-JAN-13 

thì đấy, bây giờ định dạng ngày actuel của bạn được tìm thấy.

Các vấn đề liên quan