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