10

次のフィールドを持つテーブルがあります。

レポート (テーブル名) Rep_Date (日付) Rep_Time (日付)

Rep_Time フィールドには、'01/01/1753 07:30:00' のような値があります。つまり、時間部分が関連しています。次のクエリを作成しました。

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

クエリの派生テーブル部分が実行されますが、クエリ全体を実行すると、「有効な月ではありません」というエラーが表示されます。どうしてこれなの?

これをデバッグするために; 次のクエリを実行すると:

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

私は得る:

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

UPDATE 15:58 次のクエリを実行できるようになりました。

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

WHEREただし、 MaxDate の時間部分を rep_time: と比較する句にもう 1 つのステートメントを追加する必要がありto_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATEます。機能しません。

4

3 に答える 3

28

1.

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

問題を引き起こしています。時刻形式なしで to_date を使用すると、オラクルは現在のセッションの NLS 形式を使用して変換しますが、この場合は「DD/MM/YYYY」ではない可能性があります。これをチェックして...

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.

さらに重要なのは、直接比較するのではなく、なぜcharに変換してから日付に変換するのですか

MaxDate = REP_DATE

比較の前に MaxDate の時間コンポーネントを無視する場合は、..

trunc(MaxDate ) = rep_date

代わりは。

==更新:更新された質問に基づいています。

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

問題はもっと複雑だと思います。rep_time が時間のみを意図している場合、データベースに日付として格納することはできません。文字列または日付から時間間隔まで、または秒単位の数値である必要があります (Alex に感謝します。これを参照してください)。可能であれば、日付と時刻の両方を持つ 1 つの列 rep_date を使用し、それを最大日付列と直接比較することをお勧めします。

実行中のシステムで更新を制御できない場合は、これを試すことができます。

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

いずれにせよ、時刻が正しく保存されておらず (1753 年からわかるように)、今後他の問題が発生する可能性があります。

于 2012-09-26T14:32:04.220 に答える
3

実際の日付形式を知るには、sysdate を使用してレコードを挿入します。そうすれば、実際の日付形式を見つけることができます。例えば

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

ここで、挿入されたレコードを選択します。

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

結果は

ENAME   HIREDATE
Mac     06-JAN-13

ほら、実際の日付形式が見つかりました。

于 2013-01-06T21:52:49.517 に答える
1

ALTER SESSION コマンドを使用してセッションのこのデータベース パラメータの値を変更し、必要に応じて使用することもできます。

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY';
SELECT TO_DATE('05-12-2015') FROM dual;

05/12/2015
于 2020-11-23T05:09:42.870 に答える