【问题标题】:Valid Date Checks in OracleOracle 中的有效日期检查
【发布时间】:2013-01-20 01:21:03
【问题描述】:

我有一个以 varchar 格式存储的日期值(有效日期或无效日期)。是否可以在 sql 查询中检查日期是否有效。

【问题讨论】:

    标签: oracle date


    【解决方案1】:

    是的,如果您知道格式并且很少使用 plsql。

    假设您的日期格式为'yyyy-mon-dd hh24:mi:ss'

    create function test_date(d varchar2) return varchar2
    is
      v_date date;
    begin
      select to_date(d,'yyyy-mon-dd hh24:mi:ss') into v_date from dual;
      return 'Valid';
      exception when others then return 'Invalid';
    end;
    

    现在你可以:

    select your_date_col, test_date(your_date_col)
    from your_table;
    

    【讨论】:

    • 是否可以不使用pl/sql进行检查
    • 无法创建函数?
    • 我正在使用 unix shell 文件进行数据加载,我不确定我是否可以拥有函数
    • 如果您使用 sqlldr 加载文件,那么 1. 无效的行可以/将被拒绝到 .bad 文件中。 2. 是的,您可以在 ctl 中使用函数。
    • 谢谢 Florin 会试试的。我正在使用控制文件并将遵循方法#2。
    【解决方案2】:

    你可以像这样在一个块中完成它

    BEGIN
      select TO_DATE(your_date,'YYYYMMDD') from dual; --ADD INTO V_DUMMY IN PLSQL
    EXCEPTION WHEN OTHERS THEN dbms_output.put_line('NOT A VALID DATE');
    END;
    

    【讨论】:

      【解决方案3】:

      不使用块或创建自定义函数或过程,您可以只使用下面的 select 语句,因此它返回从日期字符串解析的真实日期值,如果日期字符串无法识别,则返回 null。

      这种方法有局限性。请参阅下面的注释。

      select
        case
          when regexp_substr(DateStr,'^[[:digit:]]{2}-[[:digit:]]{2}-[[:digit:]]{4}$') is not null then
            case
              when to_number(regexp_substr(DateStr,'[^-]+',1,1))<=12 and to_number(regexp_substr(DateStr,'[^-]+',1,2))<=31
              then add_months(to_date('01-01-1900','MM-DD-YYYY'),(to_number(regexp_substr(DateStr,'[^-]+',1,3))-1900)*12+to_number(regexp_substr(DateStr,'[^-]+',1,1))-1)+to_number(regexp_substr(DateStr,'[^-]+',1,2))-1
              else null
            end
          else null
        end RealDateVal
      from MyTable
      

      本示例采用日期格式为“MM-DD-YYYY”,并假设“MyTable”具有日期字符串列“DateStr”。您可能需要根据需要进行相应调整。

      总体方法是首先检查日期字符串的格式为 ??-??-????哪里有“?”是一个数字,然后检查第一个??不大于 12(当月)和第二个 ??不大于 31(对于日期)。如果全部通过,则通过使用“add_months()”函数构建年份和月份,并使用“+”函数构建日期来组装一个日期类型的值。如果其中任何一个条件不满足,则返回 null。

      注 1:由于我们没有简单的方法来检查一年是否有 2 月 29 日,而我懒于检查一个月是否有 31 日,因此一天显示为无效的 29 日、30 日或 31 日,不会被有效性检查发现的,将被推迟到下个月。 (请参见下面的示例。)并且查询永远不会返回错误。

      注 2:“case when ... is not null then ... else ... end”是惰性的,因此它不会将“then ...”部分评估为如果不满足“when ... is not null”,则可能触发错误。此功能是整体方法的基础。相反,函数 nvl2() 不是惰性的,不能替代使用。

      示例
      '06-15-2015' -> 返回有效日期
      '06-15-2015' -> 返回 null
      '06/15/2015' -> 返回 null
      '15-06-2015' -> 返回 null
      '06-31-2015' -> 返回有效日期为 07-01-2015
      '02-30-2015' -> 返回有效日期为 03-02-2015

      走得更远: 根据您想走多远,您可以通过将解析的日期值转换回字符串并将其与原始日期字符串值进行比较来缓解“注 1”中显示的限制。

      【讨论】:

      • 其实有一个简单的方法来检查是否是Feb-29th.If year % 4 == 0 then Feb-29th is true.
      【解决方案4】:

      只需使用 to_date 函数检查日期是否有效/无效。

      BEGIN
        select TO_DATE(your_date,DateFormat) from dual;
      EXCEPTION WHEN OTHERS THEN dbms_output.put_line('NOT A VALID DATE');
      END;
      

      【讨论】:

        【解决方案5】:

        而且这种方法也是一个简单的选择语句,不使用块、自定义函数或存储过程。

        本示例假定日期格式为“MM-DD-YYYY”。它首先验证格式为“??-??-????”在哪里 ”?”是一个使用正则表达式的数字,然后验证月份(第一个“??”)不大于 12,然后使用 last_day() 函数找到给定有效年/月的最后一天,以验证是否日部分(第二个“??”)是该月的有效部分。当都有效时,使用to_date()函数解析,否则返回null。

        select
          case
            when regexp_substr(DateStr,'^[[:digit:]]{1,2}-[[:digit:]]{1,2}-[[:digit:]]{4}$') is not null
            then case
              when to_number(regexp_substr(DateStr,'[^-]+',1,1))<=12
              then case
                when to_number(regexp_substr(DateStr,'[^-]+',1,2)) <= extract(day from last_day(add_months(to_date('01-01-1900','MM-DD-YYYY'),(to_number(regexp_substr(DateStr,'[^-]+',1,3))-1900)*12+to_number(regexp_substr(DateStr,'[^-]+',1,1))-1)))
                then to_date(DateStr,'MM-DD-YYYY')
                else null
                end
              else null
              end
            else null
            end InstallDate
        from MyTable
        

        【讨论】:

          【解决方案6】:
          FUNCTION IsDate( p_str IN VARCHAR2, p_format IN VARCHAR2 ) RETURN NUMBER AS
          V_date DATE;
          BEGIN
              V_Date := TO_DATE( p_str, p_format );
              RETURN 1;
          EXCEPTION
             WHEN OTHERS THEN
                RETURN 0;
          END;
          

          呼叫:

          select lastlogin, IsDate(lastlogin,'MM/dd/yyyy  hh24:mi:ss') from users_table
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多