2016-08-27 4 views
2

従業員の会社への出席を記録する次の表があります。今のようOracleデータベースの日付順

CREATE TABLE EMP_ATNDNC 
    (
    WORK_DAY DATE       NOT NULL, 
    EMP_ID  VARCHAR2(20)     NOT NULL, 
    STATUS  VARCHAR2(1) DEFAULT '0' NOT NULL, 
    TMSTMP  TIMESTAMP, 
    RCRD_VER TIMESTAMP     NOT NULL, 

    CONSTRAINT EMP_ATNDNC_PK PRIMARY KEY(WORK_DAY,EMP_ID), 
    CONSTRAINT EMP_ATNDNC_FK_DAY FOREIGN KEY(WORK_DAY) REFERENCES SCHOOL_OPEN_RCRD(WORK_DAY), 
    CONSTRAINT EMP_ATNDNC_FK_ID FOREIGN KEY(EMP_ID) REFERENCES EMP_RCRD(EMP_ID) 
    ); 

、それは2つのレコードがあります。

WORK_DAY EMP_ID  STATUS   TMSTMP        RCRD_VER 
    29-SEP-16  1234  0  27-AUG-16 05.38.46.022000000 PM  27-AUG-16 05.38.46.022000000 PM 
    26-AUG-16  9999  0  26-AUG-16 04.50.04.628000000 PM  26-AUG-16 04.50.04.628000000 PM 

私はこのクエリを実行した場合:また

WORK_DAY EMP_ID  STATUS   TMSTMP       RCRD_VER 
    29-SEP-16  1234  0  27-AUG-16 05.38.46.022000000 PM  27-AUG-16 05.38.46.022000000 PM 

SELECT * FROM EMP_ATNDNC WHERE WORK_DAY BETWEEN TO_DATE('24-AUG-16') AND TO_DATE('30-SEP-16'); 

を私はこのレコードを取得しますこのクエリを実行すると:

SELECT * FROM EMP_ATNDNC ORDER BY WORK_DAY ASC; 

私はこの結果を得る:

WORK_DAY EMP_ID  STATUS   TMSTMP        RCRD_VER 
    29-SEP-16  1234  0  27-AUG-16 05.38.46.022000000 PM  27-AUG-16 05.38.46.022000000 PM 
    26-AUG-16  9999  0  26-AUG-16 04.50.04.628000000 PM  26-AUG-16 04.50.04.628000000 PM 

の代わりに:

WORK_DAY EMP_ID  STATUS   TMSTMP        RCRD_VER 
    26-AUG-16  9999  0  26-AUG-16 04.50.04.628000000 PM  26-AUG-16 04.50.04.628000000 PM 
    29-SEP-16  1234  0  27-AUG-16 05.38.46.022000000 PM  27-AUG-16 05.38.46.022000000 PM 

なぜこの出来事はありますか?

+1

これは起こっていることを意味しません。しかし、あなたの質問にはタイプミスがあるというコメントを書いているので、これはあなたが私たちに見せていることは自分のものを直接コピーして貼り付けるのではなく、投稿する前に何らかの編集を受けていることを意味します。間違いはおそらくその編集にあります。悪魔は詳細です。 –

+2

上記の@MikeNakisに同意します。あなたの問題はどちらも意味がありません。私が想像できる唯一の他の可能性は、 'work_day'に何らかの壊れたインデックスがあります。 – Gerrat

+0

@MikeNakis実際にこの質問を投稿する前に、'30 -SEP-2016 'と'30 -SEP-16'の両方で試してみました。 – Steve

答えて

1

あなたBETWEEN句の二日は2桁の数字で指定された年があります。

BETWEEN TO_DATE('24-AUG-2016') AND TO_DATE('30-SEP-2016'); 
:あなたのデフォルトの日付書式は、次のように変更 かもしれない作品を作る dd-mon-yyyyであると仮定すると

BETWEEN TO_DATE('24-AUG-2016') AND TO_DATE('30-SEP-16'); 
                ^^ 

ただし、TO_DATEdocumentationとして:

それは理想的にはあなたが明示的に、例えば、使用している日付フォーマットを言及する必要がありますTO_DATE

で書式マスク(FMT)を指定することは常に良い習慣です

SELECT * 
FROM EMP_ATNDNC 
WHERE WORK_DAY BETWEEN TO_DATE('24-AUG-2016', 'dd-mon-yyyy') AND 
         TO_DATE('30-SEP-2016', 'dd-mon-yyyy') 
+0

いいえ、それは役に立たなかった。まだ同じ結果が得られています – Steve

+0

** '30-SEP-2016' **は実際に私の質問のタイプミスです。私は同じことを修正しました。私は 'SELECT * FROM EMP_ATNDNC TO_DATE('24 -AUG-16'、 'dd-mon-yy')とTO_DATE('30 -SEP-16 '、' dd-mon-yy ');それでも動作しません – Steve

+0

@スティーブ見て[ここ](http://www.dba-oracle.com/f_to_date.htm)。私のクエリはAFAIKで動作するはずです。 –

3

不適切な形式のモデルで挿入されている可能性がありますが、現在の世紀にない日付があるようです。あなたは2つのinsert文1を見れば

insert into EMP_ATNDNC 
values (to_date('26-AUG-16', 'DD-MON-RRRR'), 9999, 0, 
    to_timestamp('26-AUG-16 04.50.04.628000000 PM', 'DD-MON-RR HH.MI.SS.FF AM'), 
    to_timestamp('26-AUG-16 04.50.04.628000000 PM', 'DD-MON-RR HH.MI.SS.FF AM')); 

insert into EMP_ATNDNC 
values (to_date('29-SEP-16', 'DD-MON-YYYY'), 1234, 0, 
    to_timestamp('27-AUG-16 05.38.46.022000000 PM', 'DD-MON-RR HH.MI.SS.FF AM'), 
    to_timestamp('27-AUG-16 05.38.46.022000000 PM', 'DD-MON-RR HH.MI.SS.FF AM')); 

alter session set nls_date_format = 'DD-MON-RR'; 
alter session set nls_timestamp_format = 'DD-MON-RR HH:MI:SS.FF3 AM'; 

SELECT * FROM EMP_ATNDNC WHERE WORK_DAY BETWEEN TO_DATE('24-AUG-16') AND TO_DATE('30-SEP-16'); 

WORK_DAY EMP_ID    S TMSTMP     RCRD_VER     
--------- -------------------- - ------------------------- ------------------------- 
26-AUG-16 9999     0 26-AUG-16 04:50:04.628 PM 26-AUG-16 04:50:04.628 PM 

WORK_DAY EMP_ID    S TMSTMP     RCRD_VER     
--------- -------------------- - ------------------------- ------------------------- 
29-SEP-16 1234     0 27-AUG-16 05:38:46.022 PM 27-AUG-16 05:38:46.022 PM 
26-AUG-16 9999     0 26-AUG-16 04:50:04.628 PM 26-AUG-16 04:50:04.628 PM 

:あなたとテーブル定義、証明するために

(まだこれ以上の2桁の年を使用してすべき理由は...本当にありません) RRRRを使用して2桁の年を変換しています。これは、世紀についてのいくつかの(通常は有益な)仮定を行います。この場合、 '16'を '2016'と扱います。 2番目はYYYYを使用しています。

あなたは通期の書式モデルを使用して実際の日付を照会する場合は、違いがわかります:2桁の年を使用しているものの

select to_char(work_day, 'SYYYY-MM-DD') as work_day, emp_id from emp_atndnc order by work_day; 

WORK_DAY EMP_ID    
----------- -------------------- 
0016-09-29 1234     
2016-08-26 9999     

問題は(クエリと本当にないですし、あなたのセッションのNLS設定にも依存している暗黙的な変換は@TimBiegeleisenが指摘したように、良い考えではありません)。

本当の問題はデータにあります。あなたはそれを修正することができるかもしれません。今世紀の前に何かに2000年を加える。

本当にあなたはまた、その悪いデータがどこから来たのかを知り、それをやめさせる必要があります。文字列からの暗黙的な日付変換に依存しているインサートがあり、異なるユーザーまたはアプリケーションには異なるNLS設定、特にNLS_DATE_FORMATがあります。

NLS設定に依存する暗黙のデータ変換に決して頼るべきではありません。そして、それはあなたのコントロールから外れるかもしれませんが、実際には2桁の年をもう使用するべきではありません。

+0

確かに、私はそれを念頭に置いておきます。しかし、Gerratがコメントで指摘したように、問題は壊れたインデックスによるものでした。私はテーブルを落として再作成し、クエリでうまく動作します – Steve

+0

2番目のクエリは、通常はインデックスを使用しません。インデックスが壊れているとはどのように判断しましたか?それがあった場合、なぜそれを再作成しませんでしたか?あなたがテーブルを作り直したとき、どうやってそれを再投入しましたか?あなたは古いテーブルの一年を見ましたか? –