sql - ORA-01841 : (full) year must be between -4713 and +9999, 且不为 0

标签 sql oracle

我明白

"ORA-01841: (full) year must be between -4713 and +9999, and not be 0."

基于随机日历数据。

我运行以下查询:

insert into TEMP_TBL
SELECT COUNT(ea.employee_rk) AS no_logins,
  ea.country_cd,
  ea.nsb_department,
  ea.employee_id,
  NULL,
  NULL
FROM EMPLOYEE_ACTIVITY ea
  JOIN employee_activity_ded ead
    ON ead.employee_act_ver_sk=ea.employee_act_ver_sk
  JOIN employee_start_end ese
    ON ese.employee_id    = ea.employee_sk
   AND ea.ACTIVITY_DT>=ese.START_REV
   AND ea.ACTIVITY_DT <ese.end_rev
WHERE TRUNC(ea.ACTIVITY_DT) BETWEEN to_date('01-AUG-2017','DD-MON-YYYY HH24:MI:SS') AND to_date('31-AUG-2017','DD-MON-YYYY HH24:MI:SS');


DESC TEMP_TBL;

VALUE_SEC        NUMBER
COUNTRY_CD    VARCHAR2(50 BYTE)
NSB_DEPARTMENT         VARCHAR2(50 BYTE)
EMPLOYEE_RK  VARCHAR2(32 BYTE)
ACCESS_DAY      DATE
ACCESS_TIME    DATE


DESC employee_start_end;

EMPLOYEE_VERSION_SK              NUMBER(20,0)
EMPLOYEE_SK   NUMBER(20,0)
START_REV         DATE
END_REV             DATE
EMPLOYEE_ID   VARCHAR2(32 BYTE)

EMPLOYEE_ACTIVITY 有大量列,但重要的是:

ea.ACTIVITY_DT       DATE

此错误发生在表中的随机数据上。奇怪的是,当我将 TO_DATE 添加到 ese.START_REVese.END_REV 时,错误不再出现。

ese.START_REV 和 to ese.END_REV 均采用 DATE 作为数据类型。

添加TO_DATE后,相同的查询运行没有错误:

insert into TEMP_TBL
SELECT COUNT(ea.employee_rk) AS no_logins,
  ea.country_cd,
  ea.nsb_department,
  ea.employee_id,
  NULL,
  NULL
FROM EMPLOYEE_ACTIVITY ea
  JOIN employee_activity_ded ead
    ON ead.employee_act_ver_sk=ea.employee_act_ver_sk
  JOIN employee_start_end ese
    ON ese.employee_id    = ea.employee_sk
   AND ea.ACTIVITY_DT>=to_date(ese.START_REV)
   AND ea.ACTIVITY_DT <to_date(ese.end_rev)
WHERE TRUNC(ea.ACTIVITY_DT) BETWEEN to_date('01-AUG-2017','DD-MON-YYYY HH24:MI:SS') AND to_date('31-AUG-2017','DD-MON-YYYY HH24:MI:SS');

最佳答案

[TL;DR] 鉴于您指定的数据类型,添加 TO_DATE 应该没有什么区别,并且您的原始查询应该有效。检查您所描述的表是否具有正确的所有者(并且您没有描述属于不同所有者的类似名称的表)并且是否具有您指定的数据类型,因为如果其中一个是字符串,则问题将有意义(但不如果它们都是日期就没有意义)。

What is strange is that when I add to_date to ese.START_REV and to ese.START_REV the error doesn't appear anymore.

这意味着查询以某种方式使用字符串比较语义来比较列,并将日期隐式转换为字符串,但由于您声明了 ea.ACTIVITY_DT,所以没有明显的列会导致这种情况发生>、ese.START_REVese.END_REV 都是 DATE 数据类型,应该仅使用日期比较语义而不是字符串比较语义进行比较.

查看修改后的查询:

JOIN employee_start_end ese
    ON ese.employee_id    = ea.employee_sk
   AND ea.ACTIVITY_DT>=to_date(ese.START_REV)
   AND ea.ACTIVITY_DT <to_date(ese.end_rev)

鉴于您声明 ese.START_REVese.end_rev 属于 DATE 数据类型,这实际上是:

JOIN employee_start_end ese
    ON ese.employee_id  = ea.employee_sk
   AND ea.ACTIVITY_DT  >= TO_DATE(
                            TO_CHAR(
                              ese.START_REV,
                              NLS_DATE_FORMAT
                            ),
                            NLS_DATE_FORMAT
                          )
   AND ea.ACTIVITY_DT   < TO_DATE(
                            TO_CHAR(
                              ese.end_rev,
                              NLS_DATE_FORMAT
                            ),
                            NLS_DATE_FORMAT
                          )

其中NLS_DATE_FORMAT由以下方式给出:

SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT'

当您在两次转换中使用相同的格式模型从日期转换为字符串并返回日期时,这应该对查询产生零差异。

I get the ORA-01841: (full) year must be between -4713 and +9999, and not be 0.

这可能是从字符串值到日期的隐式转换,其中 NLS_DATE_FORMAT 与字符串值的格式不匹配 - 同样,它只对您的列之一有意义一个字符串而不是日期。

如果您显示列的顺序与预期顺序不匹配,则另一个可能出现问题的地方是 INSERT 语句中。尝试将列名称添加到 INSERT 中:

INSERT INTO TEMP_TBL(
  VALUE_SEC,
  COUNTRY_CD,
  NSB_DEPARTMENT,
  EMPLOYEE_RK,
  ACCESS_DAY,
  ACCESS_TIME,
)
SELECT COUNT(ea.employee_rk) AS no_logins,
       ea.country_cd,
       ea.nsb_department,
       ea.employee_id,
       NULL,
       NULL
FROM   ...

关于sql - ORA-01841 : (full) year must be between -4713 and +9999, 且不为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46584574/

相关文章:

mysql - T-sql查询问题

oracle - 特定环境的 PL/SQL :"character string buffer too small"错误

sql - Oracle 12c - 列检查约束无法引用其他列

sql - 填写缺失值

sql - 如何从 SQL Server 2016 中的表中删除字符串中的重复项

java - 为什么请求无效转换错误代码 : 17132?

sql - 以另一个用户身份执行 Oracle 存储过程

java - 区分 SQLExceptions - Oracle 错误代码列表?

oracle - 如何在oracle中创建函数,我们可以在任何地方使用这个函数的结果

mysql - 如何将算术运算应用于 MySQL 中的聚合列?