Skip to Main Content
  • Questions
  • insert /*+append*/ into table ,can not insert null into tables

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, wu.

Asked: September 07, 2015 - 2:53 am UTC

Last updated: September 18, 2015 - 3:33 am UTC

Version: 1.0

Viewed 1000+ times

You Asked

Hi,Tom:
I create table test:the following

SQL> create table test(name varchar2(20) not null,age varchar2(30) not null);

Table created


I use conventional path loading and direct-path insert(/*+append*/)


conventional path loading:
SQL> insert into test(name,age) select '1','2' from dual where 1=2;

0 rows inserted

SQL> commit;

Commit complete

SQL> insert into test(name) select '1' from dual where 1=2;

0 rows inserted

SQL> commit;

Commit complete

above example is right.
but I use direct-path insert(/*+append*/) The following error occurred:

SQL> insert /*+append*/ into test(name,age) select '1','2' from dual where 1=2;

0 rows inserted

SQL> commit;

Commit complete

SQL> insert /*+append*/ into test(name) select '1' from dual where 1=2;

insert /*+append*/ into test(name) select '1' from dual where 1=2

ORA-01400: 无法将 NULL 插入 ("SCOTT"."TEST"."AGE")


Thanks in advance,
wugang

and Connor said...

Thanks for test script - always makes our lives easier. I've replicated what you see on my database

SQL> drop table test purge;

Table dropped.

SQL>
SQL> create table test(name varchar2(20) not null,age varchar2(30) not null);

Table created.

SQL>
SQL> insert /*+append*/ into test(name,age) select '1','2' from dual where 1=2;

0 rows created.

SQL> commit;

Commit complete.

SQL>
SQL> insert /*+append*/ into test(name) select '1' from dual where 1=2;
insert /*+append*/ into test(name) select '1' from dual where 1=2
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("ASKTOM"."TEST"."AGE")


SQL> commit;

Commit complete.


I'll offer a hypothesis as to what might be happening.

With direct mode insert, rather than inserting rows, Oracle is preparing entire blocks to be written to the datafiles. I would suspect, that in the process of preparing the block, it is examining the nullability of the columns to be populated and deciding at the point that the AGE column will not be provided by the SQL and thus errors out.

In reality, it probably *should* be making that decision *after* discovering if any rows are coming into the insert at all.

An interesting find by you, I must say. A potential workaround would be:

SQL> insert /*+append*/ into test(name,age) select '1',null from dual where 1=2;

0 rows created.


Interestingly, the documentation has this statement:


If any omitted column has a NOT NULL constraint and no default value, then the database returns an error indicating that the constraint has been violated and rolls back the INSERT statement


so it could be argued that the direct-mode insert is the more correct one ...

Hope this helps.

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

wu gang, September 08, 2015 - 2:32 am UTC

thanks