Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Cesar.

Asked: October 15, 2001 - 9:28 pm UTC

Last updated: February 04, 2005 - 2:34 pm UTC

Version: 8.1.6

Viewed 1000+ times

You Asked

I have this table

data_month
-----------------------------
month not null number(3)
value not null number(10,2)


I need something like this

...
v_update := 0;
begin
insert into data_month
(month, value)
values
(v_month, v_value);
exception
when dup_val_on_index then
v_update := 1;
when others then
null;
end;
if v_update > 0 then
begin
update data_month
set value = value + v_value
where month = v_month;
exception
when others then
null;
end;
end if;
...

but with SQL Loader... Is it possible?

Thanks!!!

and Tom said...

What I would do:

1) load the table data_month and specify errors=99999 and a bad file.

2) load the bad file into another table after you are done (these are your dups)

3) update data_month set value = ( select value from temp_table where temp_table.month = data_month.month ) where month in ( select month from temp_table );


see
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1615330671789 <code>

to see how this is reduced to a single SQL command without even using sqlldr in 9i...

Rating

  (7 ratings)

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

Comments

Ok, but...

Cesar Salas, October 16, 2001 - 12:57 pm UTC

Exists other way to do it, maybe a trigger?

Tom Kyte
October 16, 2001 - 8:11 pm UTC

Yah, you could do it view a view and instead of trigger but it would be somewhat slower...


ops$tkyte@ORA9I.WORLD> create table t ( x int primary key, y varchar2(25) );

Table created.

ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> create or replace view v as select * from t;

View created.

ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> create trigger v_trigger
  2  INSTEAD OF INSERT on V
  3  begin
  4          insert into t values ( :new.x, :new.y );
  5  exception
  6          when dup_val_on_index then
  7                  update t set y = :new.y where x = :new.x;
  8  end;
  9  /

Trigger created.

ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> insert into t values ( 1, 'hello' );

1 row created.

ops$tkyte@ORA9I.WORLD> insert into t values ( 2, 'hello' );

1 row created.

ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> REM here is the "load"
ops$tkyte@ORA9I.WORLD> 
ops$tkyte@ORA9I.WORLD> insert into v
  2  select 1, 'goodbye' from dual
  3  union all
  4  select 3, 'hello' from dual
  5  /

2 rows created.

ops$tkyte@ORA9I.WORLD> select * from t;

         X Y
---------- -------------------------
         1 goodbye
         2 hello
         3 hello

 

Slow?

Cesar Salas, October 17, 2001 - 10:44 am UTC

very very slow?
or only a little more slow?
I will use this process only one time at month (but with a huge volume of data)

Tom Kyte
October 17, 2001 - 11:18 am UTC

Huge volume of data would lead me towards my first approach but only a benchmark would tell you the truth.

The last question

Cesar Salas, October 17, 2001 - 4:13 pm UTC

Ok, if I use a 'view' and an 'instead trigger', how can I use the 'view' in SQL Loader?

I was trying with 'INTO database.my_view' but doesn't work.

Thanks!!!

Tom Kyte
October 17, 2001 - 6:54 pm UTC

darn.  I did it in 817

LOAD DATA
INFILE *
INTO TABLE OPS$TKYTE.V
REPLACE
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY "'"
trailing NULLCOLS
(x,y)
begindata
1,4
3,5

I just did that and it works for me.  I tried in 816 and sure enough, ORA-04043 object does not exist.

Sorry, I would go with the first method I suggested I guess. 

End

Cesar Salas, October 17, 2001 - 8:10 pm UTC

Yes, now my problem is the version.

Anyway thank you very much, you are brilliant!!!

SQL*Loader and Trigger

JHT, May 20, 2004 - 1:26 pm UTC

Tom,

I have to bulk load A LOT of data from a file (say with columns A, B, C) into a table with columns A,B,C,Z. The missing data is column Z which is a one-to-one mapping of data in column C. There is a lookup table that has the mapping of C and Z.

I know this is denormalizing the data, but we're doing this for performance during queries.

I was thinking I could do one of three things
1) Bulk load using sql*loader and have a trigger on the loaded table to get the column Z data from the lookup table
2) Query the lookup table and update the file with column Z data before loading it with sql*loader
3) Bulk load using sql*loader and then execute a sql statement to update all those rows where the column Z is null.

Which one of the aforementioned 3 is probably best in terms of performance? I'm thinking #3. Do you have suggestions for other methods.

Tom Kyte
May 20, 2004 - 2:22 pm UTC

either 3 or:

LOAD DATA
INFILE *
INTO TABLE DEPT
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
trailing nullcols
(DEPTNO, DNAME, LOC,
another_dname "(select dname from scott.dept where deptno = :deptno)"
)
BEGINDATA
10,"ACCOUNTING",CLEVELAND
.....


(if you are on 8i, you might need to use rows=1 in order for that to work -- but in 9i, you won't need that)






"Trigger Question" (on subject?)

Robert, February 04, 2005 - 1:29 pm UTC

Tom,

Can one CREATE a trigger in a DISABLED state?
Why? ... so one could have triggers already created (e.g.: documented in database) ... but they wouldn't begin actually WORKING until a set time when they would be ENABLED.

Thank you,

Robert.

Tom Kyte
February 04, 2005 - 2:14 pm UTC

sql reference syntax diagram says.....

no.



Just wanted to make sure I wasn't missing something...

Robert, February 04, 2005 - 2:34 pm UTC

Hey Tom,

That was the first place I checked... and I too found no 'disable[d]' within the train track diagram.

Just wanted to make sure I wasn't overlooking something!

Thank you!

Robert.