为 2000 年之前的时期插入只有 YY 格式的生日 Oracle DB

Insert Birthdate with only YY format for period before 2000 Oracle DB

我有一个文件,我可以在其中接收生日并将它们插入到我的数据库中。

格式如下

03-JUN-52

我使用以下脚本插入日期

update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-YY'); 

我也用过

update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-RR'); 

但是当我检查是否找到它时是 2074 而不是 1947。 如何将这个日期插入到我的 oracle 数据库中?

一般来说,RR 应该有效,但 - 并非在所有情况下。您必须先修复数据,因为 RR 将 return 不同的值:

  • 0049 的年份,您将在本世纪 20xx,而
  • 5099将return上个世纪,19xx

这是一个例子:

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

SQL> select
  2    to_date('03-07-52', 'dd-mm-rr') rr1,
  3    to_date('03-07-52', 'dd-mm-yy') yy1 ,
  4    --
  5    to_date('03-07-47', 'dd-mm-rr') rr2,
  6    to_date('03-07-47', 'dd-mm-yy') yy2
  7  from dual;

RR1        YY1        RR2        YY2
---------- ---------- ---------- ----------
03.07.1952 03.07.2052 03.07.2047 03.07.2047

SQL>

如您所见,RRYY 年份 47 return 2047.

的格式掩码

怎么办?将 19 连接到所有年份,例如

SQL> with test (col) as
  2    (select '03-07-52' from dual union all
  3     select '03-07-47' from dual
  4    )
  5  select col,
  6         to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr') result
  7                 ----------------             ---------------
  8  --             this is "03-07-"     "19"    the last 2 digits
  9  --
 10  from test;

COL      RESULT
-------- ----------
03-07-52 03.07.1952
03-07-47 03.07.1947

SQL>

[编辑]

如果您当前的插入脚本工作正常 - 我怀疑,关于您在评论中提到的错误代码:

ORA-01858: a non-numeric character was found where a numeric was expected

这意味着并非所有输入数据都具有相同的、预期的和正确的 DD-MON-YY 格式,那么修复生日的简单方法可能是这样的:

从所有年份大于 2000 的日期中减去 100 年

方法如下:

SQL> create table test (birthdate date);

Table created.

SQL> insert into test
  2    select to_date('03-07-52', 'dd-mm-rr') from dual union all
  3    select to_date('03-07-47', 'dd-mm-rr') from dual;

2 rows created.

SQL> select * from test;

BIRTHDATE
----------
03.07.1952
03.07.2047

SQL> update test set
  2    birthdate = add_months(birthdate, -100 * 12)
  3    where extract (year from birthdate) > 2000;

1 row updated.

SQL> select * from test;

BIRTHDATE
----------
03.07.1952
03.07.1947

SQL>

当然可以修改,如果有人真的是2000年以后出生的。


关于您遇到的错误 (ORA-01858),好吧,修复它取决于您将这些值输入 table.

的准确程度
  • 如果它是 SQL*Loader,无效值将被拒绝并存储到 .bad 文件中,您可以修复它们并稍后重新处理它们
  • 如果它使用外部 tables,您可以使用 where 子句并忽略无效行;例如,使用 regexp_like

或者,您最好的选择是确保所有 输入值都是有效日期。然后您选择的任何选项(我之前提到过)都可以正常工作而不会出现 ORA-xxxxx 错误。

按照 Littlefoot 的建议,将 19 连接到所有年份的替代方法。

to_date(regexp_replace('13-SEP-47', '([0-9]+$)', '19'), 'DD-MON-YYYY')

我建议实施 01 不被视为 1901 而是 2001 或类似的解决方案(我假设生日年份不是 1901您系统中的任何人)。

Case when substr(col, -2) < to_char(sysdate,'YY') 
     then to_date(col, 'DD-MON-YY') 
     else to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr'
End

干杯!!