Note_Tech

All technological notes.


Project maintained by simonangel-fong Hosted on GitHub Pages — Theme by mattgraham

DBA - SQL*Loader

Back


SQL*Loader


Lab: import data from csv file

scp emp.csv oracle@test.com:/home/oracle/sqlloader/emp.csv
-- drop tb if exists
DROP TABLE EMP_LOAD;

-- create tb
CREATE TABLE EMP_LOAD
(EMPNO NUMBER ,
FNAME VARCHAR2(100),
LNAME VARCHAR2(100)
);

-- query before load
SELECT * FROM EMP_LOAD;

# create a new file
touch /home/oracle/sqlloader/emp.ctl

# edit control file
vi /home/oracle/sqlloader/emp.ctl

# Load Data
# INFILE '/home/oracle/sqlloader/emp.csv'
# APPEND
# INTO Table emp_load
# FIELDS TERMINATED BY ','
# (
#     empno,
#     fname,
#     lname
# )

# load data
sqlldr control=/home/oracle/sqlloader/emp.ctl log=/home/oracle/sqlloader/emp.log

lab_loader lab_loader

lab_loader lab_loader

SELECT * FROM EMP_LOAD;

truncate table  EMP_LOAD;
vi /home/oracle/sqlloader/emp.csv

lab_loader

sqlldr control=/home/oracle/sqlloader/emp.ctl log=/home/oracle/sqlloader/emp.log

lab_loader

lab_loader


Discard File



Lab: Discard File

Filter Records

sqlplus hr@orclpdb
show user;
show con_name;

-- create tb
DROP TABLE EMP_LOAD;
CREATE TABLE EMP_LOAD
(
  EMPNO NUMBER ,
  FNAME VARCHAR2(100),
  LNAME VARCHAR2(100)
);

SELECT * FROM EMP_LOAD;
-- return none
# create dir for lab to place csv
mkdir /home/oracle/sqlloader/discard_file
# copy the emp.csv file to this dir
touch /home/oracle/sqlloader/discard_file/emp.ctl
vi /home/oracle/sqlloader/discard_file/emp.ctl

# note: we will not load empno='1008'
# using when clause to filter
Load Data
INFILE '/home/oracle/sqlloader/discard_file/emp.csv'
APPEND
INTO Table emp_load
WHEN empno <> '1008'
FIELDS TERMINATED BY ','
(
  empno,
  fname,
  lname
)
sqlldr control=/home/oracle/sqlloader/discard_file/emp.ctl log=/home/oracle/sqlloader/discard_file/emp.log

lab_loader_discard

lab_loader_discard

  • this example shows both error and filter
  • this did not generate the discard file due to ignorance of the option.
sqlplus hr@orclpdb

SELECT count(*) FROM EMP_LOAD;
--  16120

Generate Discard file

truncate table EMP_LOAD;
sqlldr control=/home/oracle/sqlloader/discard_file/emp.ctl log=/home/oracle/sqlloader/discard_file/emp.log DISCARD=emp.dsc

lab_loader_discard

lab_loader_discard


Data Loading Methods


Conventional Load


Lab: Conventional Load


show  user;
--USER is "HR"
show con_name;
--CON_NAME
--------------------------------
--ORCLPDB

drop table emp_x;
drop table dept_x;

-- create tb with constraint
create table dept_x
(
    deptno number,
    dname varchar2(100),
    constraint dept_x primary key (deptno)
 );

insert into dept_x values (1, 'sales');
commit;

select * from dept_x;
-- 1	sales

-- create tb with constraints, including fk
create table emp_x
(
    empid number,
    name varchar2(10) not null,
    gender varchar(1),
    deptno number,
    address varchar2(100),
    constraint emp_x_pk primary key (empid),
    constraint emp_x_uk1 unique  (name),
    constraint emp_x_fk1 foreign key (deptno) references dept_x(deptno),
    constraint emp_x_chq1 check ( gender in ('M','F') )
);

select * from emp_x;
-- return none
select * from user_constraints
where table_name='EMP_X';

lab_con_load


Load Valid Data

# create dir to place EMPLOYEES.csv
mkdir /home/oracle/sqlloader/con_load
touch /home/oracle/sqlloader/con_load/EMPLOYEES.ctl
vi /home/oracle/sqlloader/con_load/EMPLOYEES.ctl

# Load Data
# INFILE '/home/oracle/sqlloader/con_load/EMPLOYEES.csv'
# APPEND
# INTO Table emp_x
# FIELDS TERMINATED BY ','
# (
#   empid,
#   name,
#   gender,
#   deptno,
#   address
# )
sqlldr control=/home/oracle/sqlloader/con_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/con_load/EMPLOYEES.log

lab_con_load

  • It shows every 250 records, oracle commits the records.

lab_con_load

lab_con_load

select count(*) from emp_x;
--300

Load Data Violating Constraints

-- truncate tb
truncate table emp_x
vi /home/oracle/sqlloader/con_load/EMPLOYEES.csv

# 257,khaledalkhudari,M,1,NA
# 258,KH258,x,1,NA
# 259,KH259,M,2,NA

lab_con_load

sqlldr control=/home/oracle/sqlloader/con_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/con_load/EMPLOYEES.log

lab_con_load

  • only 297 rows imported.

lab_con_load

lab_con_load

  • This shows that when importing with conventional path load, oracle checks constraints.

Load Data with Null value

-- truncate tb
truncate table emp_x
vi /home/oracle/sqlloader/con_load/EMPLOYEES.csv
# keep the change in the previous test
# 260,,M,1,NA

lab_con_load

sqlldr control=/home/oracle/sqlloader/con_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/con_load/EMPLOYEES.log

lab_con_load

lab_con_load

lab_con_load

  • load check the not null constraint.

Load Data violating PK

-- truncate tb
truncate table emp_x;
vi /home/oracle/sqlloader/con_load/EMPLOYEES.csv
# keep the change in the previous tests
# make the id 280 = 1

lab_con_load

sqlldr control=/home/oracle/sqlloader/con_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/con_load/EMPLOYEES.log

lab_con_load

lab_con_load

lab_con_load


Load Data controling commit

truncate table emp_x;
# instruct loader to commit each 50 records.
sqlldr control=/home/oracle/sqlloader/con_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/con_load/EMPLOYEES.log ROWS=50

lab_con_load


Direct Path Load


Lab: Direct Path Load

show  user;
-- USER is "HR"
show con_name;
--CON_NAME
--------------------------------
--ORCLPDB


drop table emp_x;
drop table dept_x;
-- create tb with pk
create table dept_x
(deptno number,
 dname varchar2(100),
 constraint dept_x primary key (deptno)
 );

insert into dept_x values (1, 'sales');
commit;

select * from dept_x;
-- 1	sales

-- create tb with constraints
create table emp_x
(
    empid number,
    name varchar2(10) not null,
    gender varchar(1),
    deptno number,
    address varchar2(100),
    constraint emp_x_pk primary key (empid),
    constraint emp_x_uk1 unique  (name),
    constraint emp_x_fk1 foreign key (deptno) references dept_x(deptno),
    constraint emp_x_chq1  check ( gender in ('M','F') )
);


select * from emp_x;
-- return none

Load Valid Data

mkdir /home/oracle/sqlloader/direct_load
# place EMPLOYEES.csv in this dir
touch /home/oracle/sqlloader/direct_load/EMPLOYEES.ctl
vi /home/oracle/sqlloader/direct_load/EMPLOYEES.ctl

Load Data
INFILE '/home/oracle/sqlloader/direct_load/EMPLOYEES.csv'
APPEND
INTO Table emp_x
FIELDS TERMINATED BY ','
(
  empid,
  name,
  gender,
  deptno,
  address
)
# using DIRECT=TRUE clause
sqlldr control=/home/oracle/sqlloader/direct_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/direct_load/EMPLOYEES.log DIRECT=TRUE

lab_direct_load

lab_direct_load

select count(*) from emp_x;
-- 300

lab_direct_load

select * from user_constraints
where table_name='EMP_X';

lab_direct_load

  • only the not null, unique and pk constraints are enabled after loading.
ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_CHQ1;
ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_FK1;

-- verify
select * from user_constraints
where table_name='EMP_X';

lab_direct_load

select * from user_indexes
where table_name='EMP_X';
-- the status is valid

Load Data violating FK and Check constraints

truncate table emp_x;
vi /home/oracle/sqlloader/direct_load/EMPLOYEES.csv

# 287,KH287,x,1,NA
# 288,KH288,M,2,NA

lab_direct_load

# using DIRECT=TRUE clause
sqlldr control=/home/oracle/sqlloader/direct_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/direct_load/EMPLOYEES.log DIRECT=TRUE

lab_direct_load

  • all data are loaded without any issues because direct path load disables the check and fk constraints.
select constraint_name, constraint_type, search_condition, status
from user_constraints
where table_name='EMP_X';
--SYS_C007811	C	"NAME" IS NOT NULL	ENABLED
--EMP_X_PK	P		ENABLED
--EMP_X_UK1	U		ENABLED
--EMP_X_FK1	R		DISABLED
--EMP_X_CHQ1	C	 gender in ('M','F') 	DISABLED

ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_CHQ1;
--Error starting at line : 110 in command -
--ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_CHQ1
--Error report -
--ORA-02293: cannot validate (HR.EMP_X_CHQ1) - check constraint violated
--02293. 00000 - "cannot validate (%s.%s) - check constraint violated"
--*Cause:    an alter table operation tried to validate a check constraint to
--           populated table that had nocomplying values.
--*Action:   Obvious

ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_FK1;
--Error starting at line : 120 in command -
--ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_FK1
--Error report -
--ORA-02298: cannot validate (HR.EMP_X_FK1) - parent keys not found
--02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
--*Cause:    an alter table validating constraint failed because the table has
--           child records.
--*Action:   Obvious

Load Data violating PK, Unique, and NOT NULL constraints

-- truncate tb
truncate table emp_x;

-- enable constraints
ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_CHQ1;
ALTER TABLE emp_x ENABLE CONSTRAINT EMP_X_FK1;
vi /home/oracle/sqlloader/direct_load/EMPLOYEES.csv

# MAKE THE ID 289=1
# 290,,M,1,NA
# 291,KH1,M,1,NA

lab_direct_load

# using DIRECT=TRUE clause
sqlldr control=/home/oracle/sqlloader/direct_load/EMPLOYEES.ctl log=/home/oracle/sqlloader/direct_load/EMPLOYEES.log DIRECT=TRUE

lab_direct_load

  • one record was rejected.

lab_direct_load

  • the rejected record in bad file is the one violating the not null constraint.

lab_direct_load

  • When violating the PK and unique constraints, Oracle disable them but insert the record.
  • When violating the not null constraint, Oracle reject the record.
-- query constraints
select constraint_name, constraint_type, search_condition, status
from user_constraints
where table_name='EMP_X';
--SYS_C007811	C	"NAME" IS NOT NULL	ENABLED
--EMP_X_FK1	R		DISABLED
--EMP_X_CHQ1	C	 gender in ('M','F') 	DISABLED
--EMP_X_PK	P		DISABLED
--EMP_X_UK1	U		DISABLED

SELECT * FROM emp_x
ORDER BY  1;
-- note 2 record with pk equal to 1
--1	KH289	M	1	"NA"
--1	KH1	M	1	"NA"

SELECT * FROM emp_x
ORDER BY  2;
-- note 2 records with the same name
--1	KH1	M	1	"NA"
--291	KH1	M	1	"NA"

Summary


Express Mode


Lab: Express Mode


show  user;
--USER is "HR"
show con_name;
--CON_NAME
--------------------------------
--ORCLPDB

drop table emp_x;
drop table dept_x;

-- create tb with pk
create table dept_x
(
    deptno number,
    dname varchar2(100),
    constraint dept_x primary key (deptno)
 );

insert into dept_x values (1, 'sales');
commit;

select * from dept_x;
-- 1	sales

create table emp_x
(
    empid number,
    name varchar2(10) not null,
    gender varchar(1),
    deptno number,
    address varchar2(100),
    constraint emp_x_pk primary key (empid),
    constraint emp_x_uk1 unique  (name),
    constraint emp_x_fk1 foreign key (deptno) references dept_x(deptno),
    constraint emp_x_chq1  check ( gender in ('M','F') )
);


select * from emp_x;
-- return none

Load Valid Data

mkdir /home/oracle/sqlloader/express_mode
# place dat file
  • The csv file needs to change the extention with .dat.
cd /home/oracle/sqlloader/express_mode

sqlldr hr@orclpdb TABLE=emp_x
  • SQL*Loader first created a temporary external table, used the external table to load the content of the external data file into the table, and finally dropped the temporary external table.
  • The command will generate the log file and .log_xt file

lab_express_mode

lab_express_mode

lab_express_mode

lab_express_mode

select count(*) from emp_x;
-- 300

Load Valid Data without external tb

-- existing data
delete from emp_x;
commit;
sqlldr hr@orclpdb TABLE=emp_x DIRECT=NO

lab_express_mode


Load Valid Data with direct load

sqlldr hr@orclpdb TABLE=emp_x DIRECT=YES

lab_express_mode

Loader uses direct path the constraints are disabled all valid rows are inserted.

SELECT count(*) FROM emp_x
ORDER BY 1;
-- 598

select constraint_type, status
from user_constraints
where table_name='EMP_X';
--C	ENABLED
--R	DISABLED
--C	DISABLED
--P	DISABLED
--U	DISABLED

Load Data violating PK

delete from emp_x;
commit;
vi /home/oracle/sqlloader/express_mode/emp_x.dat
# 1,KH280,M,1,NA

sqlldr hr@orclpdb TABLE=emp_x

lab_express_mode

lab_express_mode

If any of the constraint has been violated, Oracle will not continue the loading.


Load Data violating unique constraint

vi /home/oracle/sqlloader/express_mode/emp_x.dat
# 280,KH1,M,1,NA

sqlldr hr@orclpdb TABLE=emp_x

lab_express_mode

lab_express_mode

If any of the constraint has been violated, Oracle will not continue the loading.


Load Data violating length of column

-- existing data
delete from emp_x;
commit;
vi /home/oracle/sqlloader/express_mode/emp_x.dat
# 280,KH28888888888888888888888888888,M,1,NA

sqlldr hr@orclpdb TABLE=emp_x

lab_express_mode

lab_express_mode

If a row violate the length of a colum, this row will not insert. A bad file will be created.

select count(*)
from emp_x;
-- 299

####


TOP