“ DD-MON-RR”日期格式模式无法按预期工作

Sar*_*hAk 2 oracle postgresql datetime types postgresql-9.1

我插入的查询格式为

to_date('25-JUN-13','DD-MON-RR')
Run Code Online (Sandbox Code Playgroud)

oracle中工作正常,输出为25-JUN-13
postgresql中 ,与相同0001-06-25 BC

这是一个从oracle数据库到postgresql迁移项目。任何与oracle相同的解决方案。

如果我使用的是DD-MM-YY格式,则同样无法正常工作,那么结果会有很大不同。

在PostgreSQL中运行此查询->

select to_char(to_date('25-JUN-53','DD-MON-YY'),'YYYY') as YEAR 

ANSWER IS --> 2053 
Run Code Online (Sandbox Code Playgroud)

从查询中检索与oracle中相同的结果时

select to_char(to_date('25-JUN-53','DD-MON-RR'),'YYYY') as YEAR from dual

ASSWER IS --> 1953
Run Code Online (Sandbox Code Playgroud)

当我迁移项目时,Postgresql中应该具有相同的功能,以便最终结果应该相同。

Erw*_*ter 6

同样不能正常工作...

当然可以正常工作了。每个文档:

如果年份格式规范小于四位数,例如YYY,并且提供的年份小于四位数,则将调整年份为最接近2020年,例如95变为1995年。

因此,70变为1970,但69变为2069。

Oracle对于格式说明符有不同的规则RR(Postgres中不存在),基本上将年份调整为最接近2000年(最接近当前日期的世纪):

解决方法

我会将功能封装在根据字符串中的年份切换世纪的功能中。由于Postgres允许函数重载,因此您甚至可以将相同的函数名to_date()与不同的参数类型一起使用。

根据上面的文档,Oracle在YY ='50'处回绕,并且此函数等效于2049年:

CREATE OR REPLACE FUNCTION to_date(varchar, text)
  RETURNS date AS
$func$
SELECT CASE WHEN right($1, 2) > '49' THEN
         to_date(left($1, -2) || '19' || right($1, 2), 'DD-MON-YYYY')
      ELSE
         to_date(left($1, -2) || '20' || right($1, 2), 'DD-MON-YYYY')
      END
$func$  LANGUAGE sql STABLE;
Run Code Online (Sandbox Code Playgroud)

只是STABLE,不是IMMUTABLE,因为to_date只是STABLE。否则,您将禁用函数内联。

我选择varchar的第一个参数不同于使用的原始参数text
如果年份数字> 49,则该函数将20世纪(带有“ 19”)添加,否则将21世纪添加到转换之前的日期字符串中。第二个参数被忽略

呼叫:

SELECT to_date('25-JUN-53'         , 'DD-MON-YY') AS original
     , to_date('25-JUN-53'::varchar, 'DD-MON-YY') AS patched1
     , to_date('25-JUN-53'::varchar, 'DD-MON-RR') AS patched2
     , to_date('25-JUN-53'::varchar, 'FOO-BAR')   AS patched3
Run Code Online (Sandbox Code Playgroud)

我们的自定义函数无论如何都会忽略第二个参数。

结果:

original    | patched
------------+-----------
2053-06-25  | 1953-06-25
Run Code Online (Sandbox Code Playgroud)

SQL提琴。

您可能会使工作到2049年以后变得更加复杂,并考虑第二个参数...


一个警告词:更好地完成基本函数的函数重载。如果这仍然存在于您的系统中,那么以后有人会得到令人惊讶的结果。

最好在特殊的架构中创建该函数并有search_path选择地进行设置,以便仅在适当时使用。text在这种情况下,也可以用作参数类型:

CREATE SCHEMA specialfunc;
CREATE OR REPLACE FUNCTION specialfunc.to_date(text, text) AS ...
Run Code Online (Sandbox Code Playgroud)

然后:

SET search_path = specialfunc, pg_catalog;
SELECT to_date('25-JUN-53', 'DD-MON-YY') AS patched;
Run Code Online (Sandbox Code Playgroud)

使用临时功能。看到: