Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 15 ■ DATA LOADING AND UNLOADING 661 10,Sales,Virginia,1/5/2000 20,Accounting,Virginia,21/6/1999 30,Consulting,Virginia,5/1/2000 40,Finance,Virginia,15/3/2001 you would find this error in your log file, for each input record: Record 1: Rejected - Error on table DEPT, column ENTIRE_LINE. Column not found before end of logical record (use TRAILING NULLCOLS) Here, SQLLDR is telling you that it ran out of data in the record before it ran out of columns. The solution is easy in this case, and, in fact, SQLLDR even tells us what to do: use TRAILING NULLCOLS. This will have SQLLDR bind a NULL value in for that column if no data exists in the input record. In this case, adding TRAILING NULLCOLS will cause the bind variable :ENTIRE_LINE to be NULL. So, you retry with this control file: LOAD DATA INFILE * INTO TABLE DEPT REPLACE FIELDS TERMINATED BY ',' TRAILING NULLCOLS (DEPTNO, DNAME "upper(:dname)", LOC "upper(:loc)", LAST_UPDATED date 'dd/mm/yyyy', ENTIRE_LINE ":deptno||:dname||:loc||:last_updated" ) BEGINDATA 10,Sales,Virginia,1/5/2000 20,Accounting,Virginia,21/6/1999 30,Consulting,Virginia,5/1/2000 40,Finance,Virginia,15/3/2001 Now the data in the table is as follows: ops$tkyte@ORA10G> select * from dept; DEPTNO DNAME LOC ENTIRE_LINE LAST_UPDA ------ -------------- ------------- ----------------------------- --------- 10 SALES VIRGINIA 10SalesVirginia1/5/2000 01-MAY-00 20 ACCOUNTING VIRGINIA 20AccountingVirginia21/6/1999 21-JUN-99 30 CONSULTING VIRGINIA 30ConsultingVirginia5/1/2000 05-JAN-00 40 FINANCE VIRGINIA 40FinanceVirginia15/3/2001 15-MAR-01 What makes this feat possible is the way SQLLDR builds its INSERT statement. SQLLDR will look at the preceding and see the DEPTNO, DNAME, LOC, LAST_UPDATED, and ENTIRE_LINE columns in the control file. It will set up five bind variables named after these columns. Normally, in the absence of any functions, the INSERT statement it builds is simply
662 CHAPTER 15 ■ DATA LOADING AND UNLOADING INSERT INTO DEPT ( DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE ) VALUES ( :DEPTNO, :DNAME, :LOC, :LAST_UPDATED, :ENTIRE_LINE ); It would then parse the input stream, assigning the values to its bind variables, and then execute the statement. When you begin to use functions, SQLLDR incorporates them into its INSERT statement. In the preceding example, the INSERT statement SQLLDR builds will look like this: INSERT INTO T (DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE) VALUES ( :DEPTNO, upper(:dname), upper(:loc), :last_updated, :deptno||:dname||:loc||:last_updated ); It then prepares and binds the inputs to this statement, and executes it. So, pretty much anything you can think of doing in SQL, you can incorporate into your SQLLDR scripts. With the addition of the CASE statement in SQL, doing this can be extremely powerful and easy. For example, say your input file could have dates in the following formats: • HH24:MI:SS: Just a time; the date should default to SYSDATE. • DD/MM/YYYY: Just a date; the time should default to midnight. • HH24:MI:SS DD/MM/YYYY: The date and time are both explicitly supplied. You could use a control file like this: LOAD DATA INFILE * INTO TABLE DEPT REPLACE FIELDS TERMINATED BY ',' TRAILING NULLCOLS (DEPTNO, DNAME "upper(:dname)", LOC "upper(:loc)", LAST_UPDATED "case when length(:last_updated) > 9 then to_date(:last_updated,'hh24:mi:ss dd/mm/yyyy') when instr(:last_updated,':') > 0 then to_date(:last_updated,'hh24:mi:ss') else to_date(:last_updated,'dd/mm/yyyy') end" ) BEGINDATA 10,Sales,Virginia,12:03:03 17/10/2005 20,Accounting,Virginia,02:23:54 30,Consulting,Virginia,01:24:00 21/10/2005 40,Finance,Virginia,17/8/2005
- Page 656 and 657: CHAPTER 13 ■ PARTITIONING 611 So,
- Page 658 and 659: CHAPTER 13 ■ PARTITIONING 613 Aud
- Page 660 and 661: CHAPTER 14 ■ ■ ■ Parallel Exe
- Page 662 and 663: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 664 and 665: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 666 and 667: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 668 and 669: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 670 and 671: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 672 and 673: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 674 and 675: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 676 and 677: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 678 and 679: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 680 and 681: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 682 and 683: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 684 and 685: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 686 and 687: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 688 and 689: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 690 and 691: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 692 and 693: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 694 and 695: CHAPTER 15 ■ ■ ■ Data Loading
- Page 696 and 697: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 698 and 699: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 700 and 701: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 702 and 703: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 704 and 705: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 708 and 709: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 710 and 711: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 712 and 713: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 714 and 715: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 716 and 717: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 718 and 719: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 720 and 721: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 722 and 723: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 724 and 725: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 726 and 727: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 728 and 729: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 730 and 731: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 732 and 733: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 734 and 735: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 736 and 737: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 738 and 739: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 740 and 741: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 742 and 743: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 744 and 745: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 746 and 747: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 748: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 751 and 752: 706 ■INDEX autonomous transaction
- Page 753 and 754: 708 ■INDEX CREATE ANY DIRECTORY f
- Page 755 and 756: 710 ■INDEX dedicated server, 57-5
662<br />
CHAPTER 15 ■ DATA LOADING AND UNLOADING<br />
INSERT INTO DEPT ( DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE )<br />
VALUES ( :DEPTNO, :DNAME, :LOC, :LAST_UPDATED, :ENTIRE_LINE );<br />
It would then parse the input stream, assigning the values to its bind variables, <strong>and</strong> then<br />
execute the statement. When you begin to use functions, SQLLDR incorporates them into its<br />
INSERT statement. In the preceding example, the INSERT statement SQLLDR builds will look<br />
like this:<br />
INSERT INTO T (DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE)<br />
VALUES ( :DEPTNO, upper(:dname), upper(:loc), :last_updated,<br />
:deptno||:dname||:loc||:last_updated );<br />
It then prepares <strong>and</strong> binds the inputs to this statement, <strong>and</strong> executes it. So, pretty much<br />
anything you can think of doing in SQL, you can incorporate into your SQLLDR scripts. With<br />
the addition of the CASE statement in SQL, doing this can be extremely powerful <strong>and</strong> easy. For<br />
example, say your input file could have dates in the following formats:<br />
• HH24:MI:SS: Just a time; the date should default to SYSDATE.<br />
• DD/MM/YYYY: Just a date; the time should default to midnight.<br />
• HH24:MI:SS DD/MM/YYYY: The date <strong>and</strong> time are both explicitly supplied.<br />
You could use a control file like this:<br />
LOAD DATA<br />
INFILE *<br />
INTO TABLE DEPT<br />
REPLACE<br />
FIELDS TERMINATED BY ','<br />
TRAILING NULLCOLS<br />
(DEPTNO,<br />
DNAME "upper(:dname)",<br />
LOC<br />
"upper(:loc)",<br />
LAST_UPDATED<br />
"case<br />
when length(:last_updated) > 9<br />
then to_date(:last_updated,'hh24:mi:ss dd/mm/yyyy')<br />
when instr(:last_updated,':') > 0<br />
then to_date(:last_updated,'hh24:mi:ss')<br />
else to_date(:last_updated,'dd/mm/yyyy')<br />
end"<br />
)<br />
BEGINDATA<br />
10,Sales,Virginia,12:03:03 17/10/2005<br />
20,Accounting,Virginia,02:23:54<br />
30,Consulting,Virginia,01:24:00 21/10/2005<br />
40,Finance,Virginia,17/8/2005