Oracle SQLでの日付の比較


141

1994年6月20日以降に採用された従業員数を表示しようとしていますが、「JUN」の無効な識別子というエラーが表示されます。助けてください、ありがとう!

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 

1
> <または、次のいずれかを使用できることにも注意してくださいBETWEEN '' AND ''
Andrew

回答:


296

31-DEC-95は文字列でも、でもありません20-JUN-94。それらは最後にいくつかの余分なものが追加された数字です。これは、単一引用符である'31-DEC-95''20-JUN-94'-である必要があります'。これにより、文字列を比較できます。

ただし、文字列の比較は行っていません。あなたは日付の比較を行っています。文字列を日付に変換する必要があります。組み込みTO_DATE()関数を使用するか、日付リテラルを使用します。

現在まで()

select employee_id
  from employee
 where employee_date_hired > to_date('31-DEC-95','DD-MON-YY')

この方法には、いくつかの不要な落とし穴があります

  • コメントでa_horse_with_no_nameが指摘したようにDEC、は必ずしも12月を意味するわけではありません。それはあなたNLS_DATE_LANGUAGENLS_DATE_FORMAT設定に依存します。比較がどのロケールでも機能することを確認するには、代わりに日時形式モデルを 使用できますMM
  • '95年は不正確です。あなたは1995年を意味しているのを知っていますが、それが50年だったら、それは1950年か2050年ですか 常に明確にすることが最善です
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

日付リテラル

日付リテラルはANSI標準の一部です。つまり、Oracle固有の関数を使用する必要はありません。リテラルを使用する場合は、フォーマットで日付を指定する必要ありYYYY-MM-DD、時間要素を含めることはできません。

select employee_id
  from employee
 where employee_date_hired > date '1995-12-31'

Oracleの日付データ型には時刻の要素が含まれているため、時刻の部分がない日付はに相当し1995-12-31 00:00:00ます。

時間部分を含める場合は、タイムスタンプリテラルを使用する必要があります。 YYYY-MM-DD HH24:MI:SS[.FF0-9]

select employee_id
  from employee
 where employee_date_hired > timestamp '1995-12-31 12:31:02'

さらに詳しい情報

NLS_DATE_LANGUAGEから派生しNLS_LANGUAGE、からNLS_DATE_FORMAT派生していNLS_TERRITORYます。これらは、あなたが最初にデータベースを作成したときに設定されているが、彼らはあなたのinializationパラメータファイルを変化させることによって変更することができます-使用して、またはセッション・レベルで-本当に必要な場合にのみ、ALTER SESSION構文を。例えば:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

これの意味は:

  • DD 月の日、1から31
  • MM 数値による月、01から12(1月は01)
  • YYYY4桁の年-私の意見では、これは2桁の年より常に優れYYています。なぜなら、あなたが言及している世紀との混乱はないからです。
  • HH24 一日の時間、0-23
  • MI 時間の分、0〜59
  • SS 秒、0〜59

クエリを実行するV$NLS_PARAMETERSsと、現在の言語と日付の言語設定を確認できます。クエリを実行すると、有効な値の全範囲を確認できますV$NLS_VALID_VALUES

参考文献


ちなみに、count(*)必要な場合は、グループ化する必要がありますemployee_id

select employee_id, count(*)
  from employee
 where employee_date_hired > date '1995-12-31'
 group by employee_id

これにより、あたり のカウントが得られますemployee_id


13
+1は、to_date()でフォーマットマスクを使用します。言語設定が異なるため、環境によっては失敗する可能性があることに注意してください。DEC常に有効な月であるとは限りません。通常は、名前ではなく数字を使用する方がよい
a_horse_with_no_name

1
あなたはできる ANSIリテラルとの時間を指定する-あなただけ指定する必要がtimestampリテラルの代わりに、dateリテラルを:timestamp '2015-01-30 19:42:04' (ANSI SQLにあるためdate、データ型は時間を持っていない、唯一のtimestampデータ型はありません)。
a_horse_with_no_name

1
ANSI日付リテラルは、毎回TO_DATEと日付形式を入力する必要があることを比較する本当に簡潔な方法です。私のようなLAZY開発者に適しています。注意すべきことの1つは、DATE 2016-04-01手段2016-04-01 00:00:00です。そして、この構文はOracle 9i以降で機能すると思います。これは、ANSI-SQL構文がOracleに導入された場所だからです。
LeOn-Han Li

1
私の考え方は過去4年間で大幅に進化しました@Leon :-) '答えを更新しました。日付リテラルには時間要素が含まれていないと述べましたが、あなたが述べたように、これをより明確に呼び出しました。9iの延長サポートは約6年前に終了しました...そして14年前にリリースされました。これは、大多数のユーザーにとってはもはや重要ではありません。
ベン


6

結論、

to_char 独自の方法で動作します

そう、

MM-DD-YYまたはDD-MM-YYYYまたはその他の形式の代わりに、常にこの形式YYYY-MM-DDを比較に使用します


4

次のようにtruncとto_dateを使用できます。

select TO_CHAR (g.FECHA, 'DD-MM-YYYY HH24:MI:SS') fecha_salida, g.NUMERO_GUIA, g.BOD_ORIGEN, g.TIPO_GUIA, dg.DOC_NUMERO, dg.* 
from ils_det_guia dg, ils_guia g
where dg.NUMERO_GUIA = g.NUMERO_GUIA and dg.TIPO_GUIA = g.TIPO_GUIA and dg.BOD_ORIGEN = g.BOD_ORIGEN
and dg.LAB_CODIGO = 56 
and trunc(g.FECHA) > to_date('01/02/15','DD/MM/YY')
order by g.FECHA;

2

あなたのクエリから:

Select employee_id, count(*) From Employee 
Where to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95' 

1994年6月20日以降に採用された従業員数は表示しないと思います。従業員数を表示する場合は、次のように使用できます。

Select count(*) From Employee 
Where to_char(employee_date_hired, 'YYYMMMDDD') > 19940620 

私はあなたが使用できる日付を比較するためのベストプラクティスとして:

employee_date_hired > TO_DATE('20-06-1994', 'DD-MM-YYYY');
or
to_char(employee_date_hired, 'YYYMMMDDD') > 19940620;

-4

日付は文字に変換されるため、単一引用符が必要です。

employee_id、count(*)を選択します
従業員から
where to_char(employee_date_hired、 'DD-MON-YY')> '31 -DEC-95 ';

1
このSQLは暗黙の日付形式を使用するため、常に機能するとは限りません。
Jon Heller、2014年

5
特定のNLS_ *設定でのみ正常に機能し、他のクライアントまたはサーバーでは機能しない可能性があります。受け入れられた回答は、明示的な日付形式が重要である理由を説明しています。
Jon Heller、

このメソッドは日付ではなく文字列を比較します。2番目の文字列は「3」で始まるため、比較は「アルファベット順」のように機能します。興味深いことに、このタイプの比較は、YYYY-MM-DDのような形式を使用すると実際に機能します(偶然)。しかし、もちろん、日付と日付を比較する方が良い...
Nick Perkins
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.