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;
并且惊讶:它有效!没有错误。
没有任何意义了......
答案 0 :(得分:0)
我找到了错误的起源:
TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE
如果我改用它:
TRUNC(TABLE1.DATA_DATE ,'MM') DATA_DATE
有效!
我能用MONTH重现错误。
所以它确实是TRUNC和'MONTH'的Oracle错误
谢谢大家的建议。