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

我有格式錯誤數據VARCHAR列如下提及。如何改變從日期格式「1965年8月1日00:00:00.0」到「星期二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

這就是爲什麼你不應該存儲日期/時間戳作爲字符串。你只有這兩種格式?你的第一個查詢也會拋出「ORA-01846:不是一週中的有效日子」,而不是關於TZD的事情?你假設前三行是在哪個時區?並且/或者你想要將最後三行轉換爲什麼時區? –

+0

我期待所有那些PST格式不正確 – rohitchandra

回答

1

將日期或時間戳存儲爲字符串不是一個好主意。你應該讓你的列成爲他們將要保存的數據的正確數據類型。除了允許Oracle更有效率之外,它還可以防止您存儲無效數據。

但是,如果你只是想轉換爲字符串像'1965-08-01 00:00:00.0''Tue Aug 01 00:00:00 PDT 2000'所以他們都在相同的字符串格式,你可以將這些值轉換爲時間戳與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()查找與特定格式完全匹配的行。


更一般地,任何你的字符串轉換爲實際的時間戳,您可以創建將嘗試各種不同的格式,並返回成功轉換,通過捕獲異常的第一個功能。一個簡單的蠻力方法可能是:

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並不總是被識別;我有兩個DB,我認爲它們是相同的,但是一個允許和其他的拋出「ORA-01857:不是有效的時區」。如果你看到過,你可以解決它通過治療TZD值作爲固定字符串指定它代表區域:

-- 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 

使用功能:

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    

注意,前三個假設一個時區,因爲我在英國選擇了倫敦。如果這是不會給你正確的結果,你知道那些總是​​代表一個特定的時間段,你可以通過改變最後一個塊中的函數來完成指定區域:

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

感謝亞歷克斯的快速反應。我們正在保持更改日誌在這個領域,因此有一段時間它可能會存儲文本也爲其他類別..仍然這是不工作的,因爲我有2000萬條記錄,都是不同的格式。我想保留所有的Fri Jul 01 00:00:00 PDT 1977格式 – rohitchandra

+0

@rohitchandra - 我添加了一個更直接的更新,只是將一種格式更改爲另一種格式。我誤解了我的想法。 –

相關問題