SQL 中更复杂的算法使用 CTE 更容易编写(和阅读):
with
syntax as (
select str,
str ~ '^\d{4}-\d{2}-\d{2}$' as syntax_ok,
split_part(str, '-', 1) as syy,
split_part(str, '-', 2) as smm,
split_part(str, '-', 3) as sdd
from test_date),
toint as (
select *,
case when syntax_ok then syy::int else 1900 end yy,
case when syntax_ok then smm::int else 1 end mm,
case when syntax_ok then sdd::int else 1 end dd
from source),
semantics as (
select *,
case
when mm in (1,3,5,7,8,10,12) then dd between 1 and 31
when mm in (4,6,9,11) then dd between 1 and 30
when mm = 2 then
case when yy/4*4 = yy and (yy/100*100 <> yy or yy/400*400 = yy)
then dd between 1 and 29
else dd between 1 and 28 end
else false end as valid
from toint),
result as (
select str,
case when syntax_ok and valid then str
else '1900-01-01' end as date
from semantics)
select * from result
第一个查询检查语法并将str 分成三个部分,第二个查询将这些部分转换为整数,第三个查询检查语义。
SQLFiddle.
您的评论表明您不需要如此彻底的检查,但我认为可以根据您的喜好轻松自定义此查询。