Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, lois.

Asked: August 15, 2006 - 1:29 pm UTC

Last updated: August 15, 2006 - 3:30 pm UTC

Version: don't know

Viewed 10K+ times! This question is

You Asked

Updating using sqlldr. I have a source file, stores.out, which contains data about stores. This data is currently loaded every day. I want to change this to an update, and only change those fields in my table which have actually changed in my source file. If it is possible to do an update, would I lose any new stores that might appear in my source file? I am completely new to sqlldr, so go easy. Thanks!

LOAD DATA
INFILE 'stores.out'
REPLACE INTO TABLE stores
FIELDS TERMINATED BY '|'
OPTIONALLY ENCLOSED BY '"'
(
STORE_NBR ,
STORE_NAME ,
STORE_SHORT_NAME ,
ADDR_STREET_NBR ,
ADDR_CITY_NAME ,
ADDR_ST_CODE
)


and Tom said...

you cannot update with sqlldr.

And an update will update the same set of columns every time (it would be not efficient to go slow by slow and read out a row, determine what columns changed, generate an update just for them, bind to it and execute it).

You could use a MERGE statement and an EXTERNAL TABLE:

ops$tkyte%ORA9IR2> create or replace directory data_dir as '/tmp/'
2 /

Directory created.

ops$tkyte%ORA9IR2> create table external_table
2 (EMPNO NUMBER(4) ,
3 ENAME VARCHAR2(10),
4 JOB VARCHAR2(9),
5 MGR NUMBER(4),
6 HIREDATE DATE,
7 SAL NUMBER(7, 2),
8 COMM NUMBER(7, 2) ,
9 DEPTNO NUMBER(2)
10 )
11 ORGANIZATION EXTERNAL
12 ( type oracle_loader
13 default directory data_dir
14 access parameters
15 ( fields terminated by ',' )
16 location ('emp.dat')
17 )
18 /

Table created.

ops$tkyte%ORA9IR2> !head /tmp/emp.dat
7369,SMITH,CLERK,7902,17-DEC-80,800,,20
7499,ALLEN,SALESMAN,7698,20-FEB-81,1600,300,30
7521,WARD,SALESMAN,7698,22-FEB-81,1250,500,30
7566,JONES,MANAGER,7839,02-APR-81,2975,,20
7654,MARTIN,SALESMAN,7698,28-SEP-81,1250,1400,30
7698,BLAKE,MANAGER,7839,01-MAY-81,2850,,30
7782,CLARK,MANAGER,7839,09-JUN-81,2450,,10
7788,SCOTT,ANALYST,7566,19-APR-87,3000,,20
7839,KING,PRESIDENT,,17-NOV-81,5000,,10
7844,TURNER,SALESMAN,7698,08-SEP-81,1500,0,30

ops$tkyte%ORA9IR2> create table emp
2 as
3 select *
4 from scott.emp
5 where mod(empno,2) = 0
6 /

Table created.

ops$tkyte%ORA9IR2> update emp set sal = sal/2
2 /

10 rows updated.

ops$tkyte%ORA9IR2> commit;

Commit complete.

ops$tkyte%ORA9IR2>
ops$tkyte%ORA9IR2> merge into EMP e1
2 using EXTERNAL_TABLE e2
3 on ( e2.empno = e1.empno )
4 when matched then
5 update set e1.sal = e2.sal
6 when not matched then
7 insert ( empno, ename, job, mgr, hiredate, sal, comm, deptno )
8 values ( e2.empno, e2.ename, e2.job, e2.mgr, e2.hiredate, e2.sal, e2.comm, e2.deptno )
9 /

14 rows merged.

ops$tkyte%ORA9IR2> commit;

Commit complete.


that'll update existing, insert new records.


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

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library