簡體   English   中英

如何忽略日期的轉換日期而忽略ORA-01847的錯誤日期必須在1到月份的最后一天之間

[英]How to convert date ignoring ORA-01847 error day of month must be between 1 and last day of month

我正在使用函數TO_DATE(datecolumn,'yyyymmdd' ) as DATE_REAL

執行我的SQL請求時,出現以下錯誤:

Exception in component tOracleInput_1
java.sql.SQLDataException: ORA-01847: le jour du mois doit être compris entre 1 et le dernier jour du mois

ORA-01847: "day of month must be between 1 and last day of month"

是否可以忽略這些錯誤並按原樣使用日期,即使月份中的日期大於該日期也適用於該月份?

升級到Oracle 12.2,並使用to_datedefault on conversion error子句:

to_date(datecolumn default null on conversion error, 'yyyymmdd')

(您可能需要將其嵌套在coalescecase表達式中,以在由於轉換錯誤而導致日期為空時重新嘗試轉換。)

或者,編寫自己的PL / SQL函數,該函數接受字符串和格式,例如to_date()但具有處理無效數據的其他步驟,並使用它代替to_date() (如果在12.1或更高版本上,請將其設置為pragma udf )。

create or replace function to_date_safe(p_datestr varchar2) return date
as
    l_result date;

    invalid_day_for_month exception;
    pragma exception_init(invalid_day_for_month, -1847);
    pragma udf;
begin
    begin
        l_result := to_date(p_datestr,'YYYYMMDD');
    exception
        when invalid_day_for_month then
            l_result := last_day(to_date(substr(p_datestr,1,6),'YYYYMM'));
    end;

    return l_result;
end to_date_safe;

(編輯)在Oracle 12.1中,您可以內聯SQL查詢定義一個PL / SQL函數。

create table demo (datecolumn varchar2(8));

insert all
    into demo (datecolumn) values ('20180101')
    into demo (datecolumn) values ('20180399')
    into demo (datecolumn) values ('20180299')
select * from dual;

with function to_date_safe(p_datestr varchar2) return date
     as
         invalid_day_for_month exception;
         pragma exception_init(invalid_day_for_month, -1847);
         l_result date;
     begin
         begin
             l_result := to_date(p_datestr,'YYYYMMDD');
         exception
             when invalid_day_for_month then
                 l_result := last_day(to_date(substr(p_datestr,1,6),'YYYYMM'));
         end;

         return l_result;
     end;
select datecolumn
     , to_date_safe(datecolumn) as converted_date
from   demo
/

DATECOLUMN CONVERTED_DATE
---------- -------------
20180101   01-JAN-2018
20180399   31-MAR-2018
20180299   28-FEB-2018

3 rows selected.

或者,用Java進行轉換。

您可以(如@William所述)編寫一個函數,嘗試使用您期望的格式模型將字符串轉換為日期,然后處理您希望看到的任何特定錯誤。 對於示例問題,如果希望將無效的天數視為該月的最后一天,則可以執行以下操作:

create or replace function updateDate(p_date varchar2) return date as
  l_date date;
  e_bad_day exception;
  pragma exception_init (e_bad_day, -1847);
begin
  begin
    -- try to convert
    l_date := to_date(p_date,'yyyymmdd');
  exception
    when e_bad_day then
      -- ignore the supplied day value and get last day of month
      l_date := last_day(to_date(substr(p_date, 1, 6), 'yyyymm'));
  end;
  return l_date;
end;
/

第一個to_date()在嵌套塊中。 如果那得到特定的異常-1847,則異常處理程序將嘗試僅使用字符串的前六個字符作為日期-這將為您提供該月的第一天-然后使用last_day()函數為您提供,即該月的最后一天。

快速演示通過CTE提供了一些示例值:

alter session set nls_date_format = 'YYYY-MM-DD';

with t (dt) as (
            select '20180218' from dual
  union all select '20160299' from dual
  union all select '20180299' from dual
  union all select '20160435' from dual
)
select dt, updateDate(dt)
from t;

DT       UPDATEDATE
-------- ----------
20180218 2018-02-18
20160299 2016-02-29
20180299 2018-02-28
20160435 2016-04-30

它不會處理任何其他錯誤,無論是第一次轉換還是第二次轉換(如果仍然有其他錯誤)。 根據數據的嚴重程度,您可能需要以類似方式處理其他情況。


由於您無法知道原始日期應該是什么,因此僅輸入的內容是無效的,因此將日期完全丟棄並將其視為空值(而不是月的最后一天)可能更安全,但這取決於您希望/需要如何使用不良值。

就像已經提到的那樣,您首先不應該將日期存儲為字符串-如果數據類型正確,則不會出現這些類型的問題。 那時,無效值已經被用戶捕獲並且可以被用戶糾正,而您不必嘗試猜測它們可能意味着什么。

只需檢查日期格式在數據庫中的存儲方式,並相應地更改格式即可。

例如:to_date(start_time,'dd-Mon-YYYY')

選擇開始時間,當substr('2016-04-35',9,2)> to_char(last_day(to_date(substr('2016-04-35',6,2)| | substr('2016-04-35 ',1,4),'mmyyyy')),'dd')然后to_date(substr('2016-04-35',9,2)-(substr('2016-04-35',9,2) -to_char(last_day(to_date(substr('2016-04-35',6,2)|| substr('2016-04-35',1,4),'mmyyyy')),'dd'))| | | substr('2016-04-35',6,2)|| substr('2016-04-35',1,4),'ddmmyyyy')否則to_Date(start_time)從table_name結束;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM