5

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

4

6 回答 6

10

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

假设您有 format 格式的日期'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;
于 2013-02-05T07:24:12.047 回答
4

你可以在一个块中做到这一点

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;
于 2013-02-05T07:25:28.477 回答
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” ... 不为空”不满意。此功能是整体方法的基础。相反,函数 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”中显示的限制。

于 2016-01-26T19:27:48.073 回答
1

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

BEGIN
  select TO_DATE(your_date,DateFormat) from dual;
EXCEPTION WHEN OTHERS THEN dbms_output.put_line('NOT A VALID DATE');
END;
于 2013-02-05T12:01:05.613 回答
1

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

此示例假定日期格式为“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
于 2016-01-27T00:53:00.927 回答
0
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
于 2018-01-23T18:54:30.650 回答