我有一个以 varchar 格式存储的日期值(有效日期或无效日期)。是否可以在sql查询中检查日期是否有效。
是的,如果你知道格式并且很少使用 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;
你可以像这样在一个块中完成它
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;
这种方法有局限性。请参阅下面的注释。
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 ...”部分以潜在地触发错误,在这种情况下如果“当...不为空”不满足。此功能是整个方法的基础。相反,函数 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”中显示的限制。
BEGIN
select TO_DATE(your_date,DateFormat) from dual;
EXCEPTION WHEN OTHERS THEN dbms_output.put_line('NOT A VALID DATE');
END;
此示例假设日期格式为“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
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
oracle 19 文档中找到了这个优雅的解决方案:
select cast('2024-01-07' as DATE DEFAULT '9999-12-31' ON CONVERSION ERROR, 'YYYY-MM-DD') as datum
from dual;