DATE_ENTERED
それがVARCHAR2
列であると仮定します
- 日付を文字列として保存しないでください。日付は列に格納する必要があり
DATE
ます。間違ったデータ型を使用することが問題の原因であり、正しいデータ型を使用するようにデータ モデルを修正することが適切な解決策です。
- 文字列を日付に変換する場合は
TO_DATE
、明示的な書式マスクを指定して関数を使用します。CAST
またはフォーマット マスクのTO_DATE
ない は、セッションNLS_DATE_FORMAT
がフォーマット マスクとして指定するものをすべて引き起こします。これはセッションごとに異なる可能性があるため、コードが一部のクライアントの一部のユーザーに対しては機能し、他のユーザーまたは他のクライアントに対しては機能しない可能性があり、バグを見つけるのは必然的に困難になります。
- A
DATE
は常にDATE
、文字列ではなく別のものと比較する必要があります。日付を文字列と比較すると、Oracle は暗黙的な変換を行う必要があり、これもまたセッションを使用し、NLS_DATE_FORMAT
コードの信頼性を低下させます。リテラル日付を指定する場合は、TO_DATE
関数を使用して文字列を日付に変換する (明示的な書式マスクを使用) か、ANSI 日付リテラルを使用します。
ID
それが主キーであると仮定するとDISTINCT
、せいぜい無意味であり、最悪の場合、Oracle に不要なソートを強いることになります。
最初の最善の解決策は、データ モデルを変更してDATE_ENTERED
、実際にはDATE
. これを行うと、クエリは (ANSI 日付リテラルを使用して) になります。
SELECT id
FROM accused
WHERE date_entered BETWEEN date '2013-04-12' and date '2013-04-12'
または明示的にTO_DATE
SELECT id
FROM accused
WHERE date_entered BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
何らかの理由で、間違ったデータ モデルで立ち往生している場合、保存したすべての文字列が実際に有効であれば、次のようなことができます。
SELECT id
FROM accused
WHERE to_date( date_entered, 'DD-Mon-YYYY' ) BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
ただし、取得しているエラーを考えると、テーブルに格納されている文字列が有効な日付を表していない行がテーブルに少なくともいくつかある可能性が非常に高いようです。問題は、どの行が無効であるかを把握しようとすることになります。1 つのオプションは、新しい関数を作成することです。
CREATE OR REPLACE FUNCTION my_to_date( p_date_str IN VARCHAR2,
p_format_mask IN VARCHAR2 )
RETURN DATE
IS
l_date DATE;
BEGIN
l_date := to_date( p_date_str, p_format_mask );
RETURN l_date;
EXCEPTION
WHEN others THEN
RETURN NULL;
END;
次に、クエリでその関数を使用します。
SELECT *
FROM accused
WHERE date_entered IS NOT NULL
AND my_to_date( date_entered, 'DD-Mon-YYYY' ) IS NULL
DATE_ENTERED
は、 が形式の有効な日付を表していないすべての行を返しますDD-Mon-YYYY
。最終的にこのデータを修正する必要があります。無効なデータを含む行を無視しても問題ない場合は、クエリを記述できます
SELECT id
FROM accused
WHERE my_to_date( date_entered, 'DD-Mon-YYYY' ) BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )