ORA-01400:奇怪的行为

时间:2014-02-12 15:44:00

标签: oracle insert null

Oracle Database 11g企业版11.2.0.3.0版 - 64位生产

A,B,C和D是VARCHAR2

E是DATE

(A,B,C,D,E)是TABLEDESTINATION的主要关键

truncate table TABLEDESTINATION;

INSERT  /*+ parallel(10) */  INTO TABLEDESTINATION (A,B,C,D, E)
  SELECT
    TABLE1.DATA1,
    TABLE2.DATA2,
    TABLE2.DATA3,
    NVL(TABLE3.DATA4, '-') DATA4,
    TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE
  FROM TABLE1 
    INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
    LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X
  GROUP BY 
    TABLE1.DATA1,  TABLE2.DATA2, TABLE2.DATA3, 
    NVL(TABLE3.DATA4, '-'),  TRUNC(TABLE1.DATA_DATE ,'MONTH');

会导致“ORA-01400:无法插入NULL(”USER“。”TABLEDESTINATION“。”E“)”

现在,如果我使用完全相同的查询,但使用临时表:

truncate table TABLEDESTINATION;

CREATE TABLE TEST_TABLE AS
  SELECT
    TABLE1.DATA1,
    TABLE2.DATA2,
    TABLE2.DATA3,
    NVL(TABLE3.DATA4, '-') DATA4,
    TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE
  FROM TABLE1 
    INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
    LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X
  GROUP BY 
    TABLE1.DATA1, TABLE2.DATA2, TABLE2.DATA3, 
    NVL(TABLE3.DATA4, '-'),  
    TRUNC(TABLE1.DATA_DATE ,'MONTH');

INSERT  /*+ parallel(10) */  INTO TABLEDESTINATION (A,B,C,D, E)
  select DATA1,DATA2,DATA3, DATA4, DATA_DATE
  from TEST_TABLE;

正确插入了行,没有任何错误。

现在我尝试相同的查询,但日期的NVL:

INSERT  /*+ parallel(10) */  INTO TABLEDESTINATION (A,B,C,D, E)
  SELECT
    TABLE1.DATA1,
    TABLE2.DATA2,
    TABLE2.DATA3,
    NVL(TABLE3.DATA4, '-') DATA4,
    /* -> */ NVL(TRUNC(TABLE1.DATA_DATE ,'MONTH'), SYSDATE) /* <- */ DATA_DATE
  FROM TABLE1 
    INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
    LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X
  GROUP BY 
    TABLE1.DATA1,  TABLE2.DATA2, TABLE2.DATA3, 
    NVL(TABLE3.DATA4, '-'),  
    /* -> */ NVL(TRUNC(TABLE1.DATA_DATE ,'MONTH'), SYSDATE) /* <- */
  ;

正确插入了行,没有任何错误。

逻辑上,这意味着我在DATA_DATE中有NULL值:

SELECT
  TABLE1.DATA1,
  TABLE2.DATA2,
  TABLE2.DATA3,
  NVL(TABLE3.DATA4, '-') DATA4,
  NVL(TRUNC(TABLE1.DATA_DATE ,'MONTH'), SYSDATE) DATA_DATE
FROM TABLE1 
  INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
  LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X
WHERE 
  TABLE1.DATA_DATE IS NULL
;

返回0行

SELECT
  TABLE1.DATA1,
  TABLE2.DATA2,
  TABLE2.DATA3,
  NVL(TABLE3.DATA4, '-') DATA4,
  NVL(TRUNC(TABLE1.DATA_DATE ,'MONTH'), SYSDATE) DATA_DATE
FROM TABLE1 
  INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
  LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X
WHERE 
  TRUNC(TABLE1.DATA_DATE) IS NULL
;

返回0行

如何在DATA_DATE中没有NULL值但是Oracle却抛出ORA-01400?

如何使用临时表,使用完全相同的查询,我不会得到相同的错误?

编辑: 像建议一样,我也尝试过使用DISTINCT:

INSERT  /*+ parallel(10) */  INTO TABLEDESTINATION (A,B,C,D, E)
  SELECT DISTINCT
    TABLE1.DATA1,
    TABLE2.DATA2,
    TABLE2.DATA3,
    NVL(TABLE3.DATA4, '-') DATA4,
    TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE
  FROM TABLE1 
    INNER JOIN TABLE2 ON TABLE1.DATA1 = TABLE2.DATA1 AND TABLE1.Z = TABLE2.Z
    LEFT JOIN TABLE3 ON TABLE1.X=TABLE3.X

返回以下错误: ORA-12805:并行查询服务器意外死亡

EDIT2:如果删除并行提示,我会收到此错误:“ ORA-00001:违反了唯一约束(ZRA.ZRAQX_VENTE_DOPR_MOIS_PK2)” 我仍然不明白,因为我在主键上使用GROUP BY,而且我没有任何NULL值......

EDIT3:我尝试使用隐式游标:

FOR CURTEST IN (/* same select as above */) LOOP
INSERT INTO TABLEDESTINATION (A,B,C,D,E) values (CURTEST.DATA1,CURTEST.DATA2,CURTEST.DATA3,CURTEST.DATA4, CURTEST.DATA_DATE);
END LOOP;

并且惊讶:它有效!没有错误。

没有任何意义了......

1 个答案:

答案 0 :(得分:0)

我找到了错误的起源:

TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE

如果我改用它:

TRUNC(TABLE1.DATA_DATE ,'MM') DATA_DATE

有效!

我能用MONTH重现错误。

所以它确实是TRUNC和'MONTH'的Oracle错误

谢谢大家的建议。