2016-06-24 27 views
0
select TO_TIMESTAMP_TZ('1965-08-01 00:00:00.0','Dy Mon DD HH:MM:ss TZD YYYY') from dual; 

次のようにvarchar列に間違った形式のデータがありますと述べた。日付形式を'08年8月1日00:00:00 PDT 2000 'から'01年8月1日00:00:00 PDT 2000'に変更する方法

1973-12-12 00:00:00.0 
2003-05-14 00:00:00.0 
1950-05-01 00:00:00.0 
Fri Jul 01 00:00:00 PDT 1977 
Sun Feb 01 00:00:00 PST 2015 
Wed May 14 00:00:00 PDT 2003 

すべての日付を以下のように同じ形式にしたいが、変換することはできません。

Fri Jul 01 00:00:00 PDT 1977 
Sun Feb 01 00:00:00 PST 2015 
Wed May 14 00:00:00 PDT 2003 

'Dy Mon DD HH:MM:ss TZD YYYY'フォーマットを追加すると、TZDのために有効な日付フォーマットが取得されません。

誰でもこの日付の変換に役立ち、更新クエリを使用して同じ形式で保存することができます。

+2

です文字列としての日付/タイムスタンプあなたはこれらの2つの形式しか持っていませんか?また、最初のクエリで「ORA-01846:有効な曜日ではありません」と表示されますが、TZDについては何も表示されません。最初の3つの行があると仮定しているタイムゾーンと最後の3つの行をどのタイムゾーンに変換しますか? –

+0

私はPSTがすべて正しい形式でないと予想しています – rohitchandra

答えて

1

文字列として日付やタイムスタンプを格納することはお勧めできません。列に、保持するデータの正しいデータ型を作成する必要があります。オラクルの効率を向上させるだけでなく、無効なデータの格納を防止します。

あなただけ'Tue Aug 01 00:00:00 PDT 2000''1965-08-01 00:00:00.0'のような文字列を変換したい場合は、そう、彼らはあなたが、to_timestamp()とタイムスタンプにこれらの値を変換し、彼らはfrom_tz()で表している時間帯を指定して、戻ってそれらを変換することができ、すべて同じ文字列の形式でありますあなたが望む形式で文字列に変換します。あなたのサンプルデータで構築されたデモ・テーブルtで:

update t set str = to_char(from_tz(to_timestamp(str, 'YYYY-MM-DD HH24:MI:SS.FF'), 
    'America/Los_Angeles'), 'Dy Mon DD HH24:MI:SS TZD YYYY') 
where str not like '%PDT%' and str not like '%PST%'; 

3 rows updated. 

select * from t; 

STR       
---------------------------- 
Wed Dec 12 00:00:00 PST 1973 
Wed May 14 00:00:00 PDT 2003 
Mon May 01 00:00:00 PDT 1950 
Fri Jul 01 00:00:00 PDT 1977 
Sun Feb 01 00:00:00 PST 2015 
Wed May 14 00:00:00 PDT 2003 

6 rows selected 

あなたはそれがそれらがエラーであろうから、ターゲット形式にすでに存在するすべての行を無視するように、フィルタを適用する必要があります。ここでは、PDTまたはPSTを含むものは除外しました。表示されていない他のフォーマットをお持ちの場合は、regexp_like()を使用して、特定のフォーマットに正確に一致する行を探してください。より一般的に


、あなたは様々な形式をしようと例外を捕捉することにより、成功裏に変換する第1の1を返す関数を作成することができ、実際のタイムスタンプにあなたの文字列のいずれかを変換します。単純なブルートフォースのアプローチは次のようなものです:

create or replace function my_to_timestamp_tz(p_str varchar2) 
return timestamp with time zone as 
begin 
    -- try each expected pattern in turn 

    begin 
    return to_timestamp_tz(p_str, 'Dy Mon DD HH24:MI:SS TZD YYYY'); 
    exception 
    when others then 
     null; 
    end; 

    begin 
    -- unspecified TZ; this assumes same as server 
    return to_timestamp_tz(p_str, 'YYYY-MM-DD HH24:MI:SS.FF'); 
    exception 
    when others then 
     null; 
    end; 

    -- maybe throw an exception if no conversions worked 
    return null; 
end; 
/

PDT/PSTは常に認識されません。 "ORA-01857:有効なタイムゾーンではありません"という2つのDBがあります。最初の3が想定していること

with t (str) as (
    select '1973-12-12 00:00:00.0' from dual 
    union all select '2003-05-14 00:00:00.0' from dual 
    union all select '1950-05-01 00:00:00.0' from dual 
    union all select 'Fri Jul 01 00:00:00 PDT 1977' from dual 
    union all select 'Sun Feb 01 00:00:00 PST 2015' from dual 
    union all select 'Wed May 14 00:00:00 PDT 2003' from dual 
) 
select str, my_to_timestamp_tz(str) as converted 
from t; 

STR       CONVERTED           
---------------------------- ---------------------------------------------------- 
1973-12-12 00:00:00.0  1973-12-12 00:00:00 Europe/London     
2003-05-14 00:00:00.0  2003-05-14 00:00:00 Europe/London     
1950-05-01 00:00:00.0  1950-05-01 00:00:00 Europe/London     
Fri Jul 01 00:00:00 PDT 1977 1977-07-01 00:00:00 America/Los_Angeles    
Sun Feb 01 00:00:00 PST 2015 2015-02-01 00:00:00 America/Los_Angeles    
Wed May 14 00:00:00 PDT 2003 2003-05-14 00:00:00 America/Los_Angeles    

注意:この関数を使用して

-- if your DB doesn't recognise PDT/PST then force them to a region: 
    begin 
    return from_tz(to_timestamp_tz(p_str, 'Dy Mon DD HH24:MI:ss "PDT" YYYY'), 
     'America/Los_Angeles'); 
    exception 
    when others then 
     null; 
    end; 

    begin 
    return from_tz(to_timestamp_tz(p_str, 'Dy Mon DD HH24:MI:ss "PST" YYYY'), 
     'America/Los_Angeles'); 
    exception 
    when others then 
     null; 
    end; 

    -- other time zone abbreviations and matching regions if you expect any 

:あなたも、あなたがそれを表している地域の固定文字列と指定するのとTZD値を処理することにより、それを回避できることを確認した場合タイムゾーン、そして私はイギリスのピック・ロンドンでこれを実行しているからです。それはあなたのために右の結果を与えるつもりはない、あなたはそれらを常に特定のタイムゾーンを表し、あなたが行う関数で最後のブロックを変更することで、そのゾーンを指定することができることを知っている場合:その意志

begin 
    -- unspecified TZ; assume from a specific region 
    return from_tz(to_timestamp(p_str, 'YYYY-MM-DD HH24:MI:SS.FF'), 
     'America/Los_Angeles'); 
    exception 
    ... 

その後、取得する:あなたが保管してはならない、なぜあなたが本当に文字列に戻って生成されたタイムスタンプを変換することができますしたい場合は

STR       CONVERTED           
---------------------------- ---------------------------------------------------- 
1973-12-12 00:00:00.0  1973-12-12 00:00:00 America/Los_Angeles    
2003-05-14 00:00:00.0  2003-05-14 00:00:00 America/Los_Angeles    
1950-05-01 00:00:00.0  1950-05-01 00:00:00 America/Los_Angeles    
Fri Jul 01 00:00:00 PDT 1977 1977-07-01 00:00:00 America/Los_Angeles    
Sun Feb 01 00:00:00 PST 2015 2015-02-01 00:00:00 America/Los_Angeles    
Wed May 14 00:00:00 PDT 2003 2003-05-14 00:00:00 America/Los_Angeles    

が、私は本当にあなたが正しいデータ型として保存をお勧めしたい

+0

素早く応答するためにAlexに感謝します。私たちはこのフィールドに変更ログを残しているので、他のカテゴリのテキストも保存することができます。まだ20万レコードあり、すべてが異なるフォーマットです。 Jul 01 00:00:00 PDT 1977 format only – rohitchandra

+0

@rohitchandra - あるフォーマットをもう一方のフォーマットに変更するために、より直進的なアップデートを追加しました。私は考えている質問を誤解しました。 –

関連する問題