gui*_*i42 5 oracle null insert
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');
Run Code Online (Sandbox Code Playgroud)
将导致"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;
Run Code Online (Sandbox Code Playgroud)
正确插入行,没有任何错误.
现在我尝试相同的查询,但使用日期的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) /* <- */
;
Run Code Online (Sandbox Code Playgroud)
正确插入行,没有任何错误.
从逻辑上讲,这意味着我在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
;
Run Code Online (Sandbox Code Playgroud)
返回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
;
Run Code Online (Sandbox Code Playgroud)
返回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
Run Code Online (Sandbox Code Playgroud)
返回以下错误:ORA-12805:并行查询服务器意外死亡
编辑2:如果我删除并行提示,我收到此错误:" 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;
Run Code Online (Sandbox Code Playgroud)
而且意外:它有效!没有错误.
没有任何意义了......
我找到了错误的根源:
TRUNC(TABLE1.DATA_DATE ,'MONTH') DATA_DATE
Run Code Online (Sandbox Code Playgroud)
如果我用这个代替:
TRUNC(TABLE1.DATA_DATE ,'MM') DATA_DATE
Run Code Online (Sandbox Code Playgroud)
有用 !
一个月后我能够重现该错误。
所以这确实是 Oracle 的 TRUNC 和“MONTH”错误
谢谢大家的建议。