Oracle
Database 11g企业版11.2.0.3.0版 – 64位生产
A,B,C和D是VARCHAR2
E是DATE
(A,C,D,E)是TABLEDESTINATION的主要关键
truncate table TABLEDESTINATION; INSERT /*+ parallel(10) */ INTO TABLEDESTINATION (A,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,'-'),'MONTH');
将导致“ORA-01400:无法插入NULL(”USER“.”TABLEDESTINATION“.”E“)”
现在,如果我使用完全相同的查询,但使用临时表:
truncate table TABLEDESTINATION; CREATE TABLE TEST_TABLE AS SELECT TABLE1.DATA1,'MONTH'); INSERT /*+ parallel(10) */ INTO TABLEDESTINATION (A,E) select DATA1,DATA2,DATA3,DATA4,DATA_DATE from TEST_TABLE;
正确插入行,没有任何错误.
现在我尝试相同的查询,但使用日期的NVL:
INSERT /*+ parallel(10) */ INTO TABLEDESTINATION (A,/* -> */ 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,SYSDATE) /* <- */ ;
正确插入行,没有任何错误.
从逻辑上讲,这意味着我在DATA_DATE中有NULL值:
SELECT TABLE1.DATA1,NVL(TRUNC(TABLE1.DATA_DATE,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,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,E) SELECT DISTINCT TABLE1.DATA1,'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
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,E) values (CURTEST.DATA1,CURTEST.DATA2,CURTEST.DATA3,CURTEST.DATA4,CURTEST.DATA_DATE); END LOOP;
而且意外:它有效!没有错误.
没有任何意义了……