Skip to Main Content
  • Questions
  • append during import -- dealing with structural changes during import.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Hemalatha.

Asked: June 13, 2000 - 1:48 am UTC

Last updated: September 13, 2005 - 12:49 pm UTC

Version: version 8.1.5

Viewed 1000+ times

You Asked

1. when I import the data, Can I append that into the existing data in the database. Assume both changes in the structure of data, No changes in the structure of data.

2. When I import the data, if there is change in structure of data, the data wont be imported. If i want to import with changes, what should i do.

and Tom said...

The answer to 1) is absolutely yes. Here is an example showing that at work:

ops$tkyte@8i> drop table t;
Table dropped.

ops$tkyte@8i> create table t ( x int );
Table created.

ops$tkyte@8i> insert into t values ( 1 );
1 row created.

ops$tkyte@8i> commit;
Commit complete.



ops$tkyte@8i> host exp userid=/ tables=t

Export: Release 8.1.5.0.0 - Production on Tue Jun 13 07:09:23 2000
(c) Copyright 1999 Oracle Corporation. All rights reserved.
Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
Export done in US7ASCII character set and US7ASCII NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table T 1 rows exported
Export terminated successfully without warnings.

ops$tkyte@8i> host imp userid=/ full=y ignore=y

Import: Release 8.1.5.0.0 - Production on Tue Jun 13 07:09:25 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production

Export file created by EXPORT:V08.01.05 via conventional path
import done in US7ASCII character set and US7ASCII NCHAR character set
. importing OPS$TKYTE's objects into OPS$TKYTE
. . importing table "T" 1 rows imported
Import terminated successfully without warnings.

ops$tkyte@8i>
ops$tkyte@8i> select * from t;

X
----------
1
1


So, that shows that the table was appended to. As for 2, the answer is also yes (but we might need help). There are 3 cases to consider

- you've ADDED a column (no work on your part needed, we'll put a NULL in it)

- you've DROPPED a column (some work on your part)

- you've changed the datatype of a column.

Here is an example of each of the three. For the added_a_column case, we need do nothing. For the dropped and modified columns, we will import into a view with an instead of trigger that we use to perform whatever data remapping we need. In our case, we will just ignore the dropped column and we will convert a NUMBER into a DATE.

ops$tkyte@8i> create table added_a_column ( x int );
Table created.

ops$tkyte@8i> create table dropped_a_column ( x int, y int );
Table created.

ops$tkyte@8i> create table modified_a_column( x int, y int );
Table created.

ops$tkyte@8i> insert into added_a_column values ( 1 );
1 row created.

ops$tkyte@8i> insert into dropped_a_column values ( 1, 1 );
1 row created.

ops$tkyte@8i> insert into modified_a_column values ( 1, 1 );
1 row created.

ops$tkyte@8i> commit;
Commit complete.

ops$tkyte@8i> host exp userid=/ 'tables=(added_a_column,dropped_a_column,modified_a_column)'

Export: Release 8.1.5.0.0 - Production on Tue Jun 13 07:23:49 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
Export done in US7ASCII character set and US7ASCII NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table ADDED_A_COLUMN 1 rows exported
. . exporting table DROPPED_A_COLUMN 1 rows exported
. . exporting table MODIFIED_A_COLUMN 1 rows exported
Export terminated successfully without warnings.

So, that constitutes our test case. We have exported the three tables "as is". Now, lets modify them:


ops$tkyte@8i> alter table added_a_column add ( y int );
Table altered.

ops$tkyte@8i> alter table dropped_a_column drop column y;
Table altered.

ops$tkyte@8i> delete from modified_a_column;
1 row deleted.

ops$tkyte@8i> alter table modified_a_column modify y date;
Table altered.


Now, if we attempt to import, we will find that "added_a_column" works OK but the rest fail


ops$tkyte@8i> host imp userid=/ full=y ignore=y

Import: Release 8.1.5.0.0 - Production on Tue Jun 13 07:23:49 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production

Export file created by EXPORT:V08.01.05 via conventional path
import done in US7ASCII character set and US7ASCII NCHAR character set
. importing OPS$TKYTE's objects into OPS$TKYTE
. . importing table "ADDED_A_COLUMN" 1 rows imported
. . importing table "DROPPED_A_COLUMN"
IMP-00058: ORACLE error 904 encountered
ORA-00904: invalid column name
. . importing table "MODIFIED_A_COLUMN"
IMP-00058: ORACLE error 932 encountered
ORA-00932: inconsistent datatypes
Import terminated successfully with warnings.


Ok, so now we have to put into the database views that look like the original tables. To accomplish this we will:

o rename the tables for a minute
o create a view that selects constants out of the right type -- eg: "select 1" for a number, "select sysdate" for a date, "select rpad( '*', 30, '*' )" for a varchar2(30) and so on
o create an instead of trigger that "does the right thing" for us, performing any data conversion/mapping we need


ops$tkyte@8i> rename modified_a_column to modified_a_column_TEMP;
Table renamed.

ops$tkyte@8i> create or replace view modified_a_column
2 as
3 select 1 x, 1 y from modified_a_column_TEMP;
View created.

ops$tkyte@8i> create or replace trigger modified_a_column_IOI
2 instead of insert on modified_a_column
3 begin
4 insert into modified_a_column_TEMP
5 ( x, y )
6 values
7 ( :new.x, sysdate+:new.y );
8 end;
9 /
Trigger created.

Here we are converting the number that was stored in Y into an offset from sysdate (why -- cause that was my "data mapping algorithm"). You would perform whatever conversion from string to date, date to number, number to string etc -- you wanted to here.

Now we take care of the dropped column:


ops$tkyte@8i> rename dropped_a_column to dropped_a_column_TEMP;
Table renamed.

ops$tkyte@8i> create or replace view dropped_a_column
2 as
3 select 1 x, 1 y from dropped_a_column_TEMP;
View created.

ops$tkyte@8i>
ops$tkyte@8i> create or replace trigger dropped_a_column_IOI
2 instead of insert on dropped_a_column
3 begin
4 insert into dropped_a_column_TEMP
5 ( x )
6 values
7 ( :new.x );
8 end;
9 /

Trigger created.


Here we are just getting rid of :new.y. We do not do anything with it -- just ignore it. It needs to be in the view so imp has something to insert into but we discard it in the trigger

Now we are ready to import again:


ops$tkyte@8i> host imp userid=/ full=y ignore=y

Import: Release 8.1.5.0.0 - Production on Tue Jun 13 07:23:50 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production

Export file created by EXPORT:V08.01.05 via conventional path
import done in US7ASCII character set and US7ASCII NCHAR character set
. importing OPS$TKYTE's objects into OPS$TKYTE
. . importing table "ADDED_A_COLUMN" 1 rows imported
. . importing table "DROPPED_A_COLUMN" 1 rows imported
. . importing table "MODIFIED_A_COLUMN" 1 rows imported
Import terminated successfully without warnings.

Now the import runs cleanly... We need to go into the database and drop our views and rename our tables now:

ops$tkyte@8i> drop view modified_a_column;
View dropped.

ops$tkyte@8i> drop view dropped_a_column;
View dropped.

ops$tkyte@8i> rename dropped_a_column_TEMP to dropped_a_column;
Table renamed.

ops$tkyte@8i> rename modified_a_column_TEMP to modified_a_column;
Table renamed.


When we look at the data, we expect to see:

o 3 rows in added_a_column from the original insert and 2 imports
o 2 rows in dropped_a_column from the original insert and 1 import that worked on it
o 1 row in modified_a_column since we had to empty that table prior to altering the column type.


ops$tkyte@8i> select * from added_a_column;

X Y
---------- ----------
1
1
1

ops$tkyte@8i> select * from dropped_a_column;

X
----------
1
1

ops$tkyte@8i> select * from modified_a_column;

X Y
---------- ---------
1 14-JUN-00

ops$tkyte@8i>

Rating

  (10 ratings)

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

Comments

Pichaimani, May 02, 2001 - 4:57 pm UTC

Hi Tom,
Thanks a lot for all these wonderful case scenarios and solutions. I've really started enjoying working in Oracle.


Helena Markova, November 20, 2001 - 2:55 am UTC


partitioning

Anna, August 19, 2002 - 7:08 pm UTC

Tom, do you have any trick like this for cases when export was done from partitioned table and target server does not have partitioning enabled?

Tom Kyte
August 20, 2002 - 7:32 am UTC

I don't have any instances without partitiong but I did do this:

ops$tkyte@ORA817DEV.US.ORACLE.COM> CREATE TABLE t
  2  (
  3    x int primary key,
  4    collection_year int
  5  )
  6  PARTITION BY RANGE (COLLECTION_YEAR) (
  7    PARTITION PART_95 VALUES LESS THAN (1996) ,
  8    PARTITION PART_96 VALUES LESS THAN (1997) ,
  9    PARTITION PART_97 VALUES LESS THAN (1998) ,
 10    PARTITION PART_98 VALUES LESS THAN (1999) ,
 11    PARTITION PART_99 VALUES LESS THAN (2000) ,
 12    PARTITION PART_00 VALUES LESS THAN (2001) ,
 13    PARTITION PART_01 VALUES LESS THAN (MAXVALUE)
 14  )
 15  ;

Table created.

ops$tkyte@ORA817DEV.US.ORACLE.COM> 
ops$tkyte@ORA817DEV.US.ORACLE.COM> 
ops$tkyte@ORA817DEV.US.ORACLE.COM> insert into t
  2  select rownum, 1995+mod(rownum,7) from all_objects;

23620 rows created.

ops$tkyte@ORA817DEV.US.ORACLE.COM> commit;

Commit complete.

ops$tkyte@ORA817DEV.US.ORACLE.COM> !exp userid=/ tables=t

Export: Release 8.1.7.4.0 - Production on Tue Aug 20 07:29:03 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production
With the Partitioning option
JServer Release 8.1.7.4.0 - Production
Export done in WE8ISO8859P1 character set and WE8ISO8859P1 NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table                              T
. . exporting partition                        PART_95       3374 rows exported
. . exporting partition                        PART_96       3375 rows exported
. . exporting partition                        PART_97       3375 rows exported
. . exporting partition                        PART_98       3374 rows exported
. . exporting partition                        PART_99       3374 rows exported
. . exporting partition                        PART_00       3374 rows exported
. . exporting partition                        PART_01       3374 rows exported
Export terminated successfully without warnings.

ops$tkyte@ORA817DEV.US.ORACLE.COM> drop table t;

Table dropped.
<b>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t ( x int, collection_year int );

Table created.

ops$tkyte@ORA817DEV.US.ORACLE.COM> !imp userid=/ tables=t ignore=y
</b>
Import: Release 8.1.7.4.0 - Production on Tue Aug 20 07:29:29 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production
With the Partitioning option
JServer Release 8.1.7.4.0 - Production

Export file created by EXPORT:V08.01.07 via conventional path
import done in WE8ISO8859P1 character set and WE8ISO8859P1 NCHAR character set
. importing OPS$TKYTE's objects into OPS$TKYTE
. . importing partition                  "T":"PART_95"       3374 rows imported
. . importing partition                  "T":"PART_96"       3375 rows imported
. . importing partition                  "T":"PART_97"       3375 rows imported
. . importing partition                  "T":"PART_98"       3374 rows imported
. . importing partition                  "T":"PART_99"       3374 rows imported
. . importing partition                  "T":"PART_00"       3374 rows imported
. . importing partition                  "T":"PART_01"       3374 rows imported
Import terminated successfully without warnings.

ops$tkyte@ORA817DEV.US.ORACLE.COM> select count(*) from t;

  COUNT(*)
----------
     23620


Have you tried using ignore=y on a pre-created table? 

This would be a lifesaver if I could get it to work!

Janine Sisk, September 17, 2002 - 1:52 pm UTC

The column I am trying to drop is a LOB column, and it's just not working for me. I've followed the steps - renamed the table, created the view (matching each dummy value selected to the datatype of its column), created the trigger, and imp'd just that file. Everything looks fine, but it always fails with ORA-00932: inconsistent datatypes, and no rows are inserted into the table.

I'm guessing this has something to do with the way imp handles LOB data. Very frustrating!

Tom Kyte
September 17, 2002 - 8:04 pm UTC

Yes, as you can imagine -- LOBS and LONGS are "special" and take some very special handling.

You'll need to imp into a table -- rename the table and then CREATE NEW_TABLE as select from this table to perform any sort of conversions.

reader

A reader, September 09, 2005 - 11:35 am UTC

Is the instead of trigger strategy work efficiently,
if we want to import from export taken from a table with
name table1 from another database to table with name table2,
both have identical structure. The export have
large volume of data

Tom Kyte
September 09, 2005 - 11:41 am UTC

if they have the same structure, a view without any triggers would be sufficient.

reader

A reader, September 09, 2005 - 12:35 pm UTC

Thanks

reader

A reader, September 10, 2005 - 10:45 am UTC

If I use the view strategy to imp to table with another
name, I found that it is necessary to grant "create table"
privilege to the importer, because it seems oracle before
importing and finds the view, wants to make sure the
importing user ( user where objects will be
imported ) has the privilege to create table.

Is there a way to get around this. I like to give
absolute necessary permissions if possible


Tom Kyte
September 10, 2005 - 11:47 am UTC

It is not that it checks to see if you have the privilege, it is that it tries to create the table, that fails with ORA-01031 and NOT ORA-00955.

It therefore fails (ignore=y doesn't come into play)

They will need create table via a grant or a role they are granted.

reader

A reader, September 13, 2005 - 9:48 am UTC

what will be the minimum grants needed for
imp as well as exp of objects owned by user (ex: u1) other
than the user (ex: u2) who is running imp, exp

Tom Kyte
September 13, 2005 - 12:26 pm UTC

depends on what you are trying to import - could be create sequence, create table, create function , etc etc etc.


reader

A reader, September 13, 2005 - 11:10 am UTC

The test I performed on imp, reveals that, if any user
can insert into a database table (ex:u1.t1), that user
will be able imp data into the database table (ex:u1.t1)
as well.

I am trying to find the minimum grants for exp
a database object of another user

Tom Kyte
September 13, 2005 - 12:49 pm UTC

no, they would need create table -- else the attempted table create imp will do fails (even with ignore=y)

reader

A reader, September 13, 2005 - 4:58 pm UTC

"
depends on what you are trying to import - could be create sequence, create 
table, create function , etc etc etc.
"

As for exp, I tried to grant to an user the individual
privs from EXP_FULL_DATABASE the following
5 sys privs
27 table privs
and 2 role_privs
Still could not exp table owned by another user.
However if I grant EXP_FULL_DATABASE, I can

Also for some reason not able to grant the following
SQL> grant "ADMINISTER RESOURCE MANAGER" to user1;
grant "ADMINISTER RESOURCE MANAGER" to user1
      *
ERROR at line 1:
ORA-01919: role 'ADMINISTER RESOURCE MANAGER' does not exist

 

More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.