在用SQL Loader加载数据时,有两个问题,求解决:
1.因为我的数据文件没有扩展名,结果我在导入时,oracle自动加上.dat扩展名。是否可以进行限制,不让oracle自动加上.dat的默认扩展名?2.因为导入的数据中有日期类型,而我在控制文件中并没有指定具体类型。是否可以在进行什么设置,让Sqlloader自动识别指定的日期格式,而不需要指定去每个一字段指定日期类型格式。谢谢。

解决方案 »

  1.   

    -- *3) 如何加载日期? ( P665 )
    -- 使用SQLLDR加载日期相当简单,但是看起来这个方面经常导致混淆。你只需在控制文件中使用DATE数据类型,并指定要使用的日期掩码。
    -- 这个日期掩码与数据库中TO_CHAR和TO_DATE中使用的日期掩码是一样的。SQLLDR会向数据应用这个日期掩码,并为你完成加载。-- 例如,如果再把DEPT表修改如下:
    alter table dept add last_updated date;-- 可以用以下控制文件加载它:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY ','
    ( DEPTNO,
      DNAME,
      LOC,
      LAST_UPDATED date 'dd/mm/yyyy'
    )
    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-- 所得到的DEPT表如下所示:eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        LAST_UPDATED
    ---------- ---------------------------- -------------------------- -------------------
            10 Sales                        Virginia                   2000-05-01 00:00:00
            20 Accounting                   Virginia                   1999-06-21 00:00:00
            30 Consulting                   Virginia                   2000-01-05 00:00:00
            40 Finance                      Virginia                   2001-03-15 00:00:00-- 就这么简单。只需在控制文件中应用格式,SQLLDR就会为我们完成日期转换。在某些情况下,可能使用一个更强大的SQL函数更为合适。例如,
    -- 如果你的输入文件包含多种不同格式的日期:有些有时间分量,有些没有;有些采用DD-MON-YYYY格式;有些格式为DD/MM/YYYY;等等。
    -- 在下一节中你会了解到如何在SQLLDR中使用函数来解决这些问题。
      

  2.   

    -- 15.1 SQL*Loader
    -- SQL*Loader(SQLLDR)是Oracle的高速批量数据加载工具。这是一个非常有用的工具,可用于从多种平面文件格式向Oracle数据库中加载数据。
    -- SQLLDR可以在极短的时间内加载数量庞大的数据。它有两种操作模式:
    -- *(01) 传统路径(conventional path):SQLLDR会利用SQL插入为我们加载数据。
    -- *(02) 直接路径(direct path):采用这种模式,SQLLDR不使用SQL;而是直接格式化数据库块。-- 利用直接路径加载,你能从一个平面文件读数据,并将其直接写至格式化的数据库块,而绕过整个SQL引擎和undo生成,同时还可能避开redo生成。
    -- 要在一个没有任何数据的数据库中充分加载数据,最快的方法就是采用并行直接路径加载。......-- 需要指出,在Oracle 8.1.6 Release 1及以上版本中,Oracle调用接口(Oracle Call Interface, OCI)允许使用C编写你自己的直接路径加载工具。
    -- 如果你要执行的操作在SQLLDR中做不到,或者如果需要SQLLDR与你的应用无缝集成,Oracle OCI就很有用。SQLLDR是一个命令行工具(也就是说,这是一个单独的程序)。
    -- 它并非一个API,例如,不能“从PL/SQL调用”。......-- 要使用SQLLDR,需要有一个控制文件(control file)。控制文件中包含描述输入数据的信息(如输入数据的布局、数据类型等),另外还包含有关目标表的信息。
    -- 控制文件甚至还可以包含要加载的数据。在下面的例子中,我们将一步一步地建立一个简单的控制文件,并对这些命令提供必要的解释
    -- (注意,代码左边加括号的数并不是控制文件中的一部分,显示这些数只是为了便于引用)。(01) LOAD DATA
    (02) INFILE *
    (03) INTO TABLE DEPT
    (04) FIELDS TERMINATED BY ','
    (05) (DEPTNO, DNAME, LOC )
    (06) BEGINDATA
    (07) 10,Sales,Virginia
    (08) 20,Accounting,Virginia
    (09) 30,Consulting,Virginia
    (10) 40,Finance,Virginia-- *(01) LOAD DATA:这会告诉SQLLDR要做什么(在这个例子中,则指示要加载数据)。SQLLDR还可以执行CONTINUE_LOAD,也就是继续加载。
    --     只有在继续一个多表直接路径加载时才能使用后面这个选项。
    -- *(02) INFILE *:这会告诉SQLLDR所要加载的数据实际上包含在控制文件本身中,如第6~10行所示。也可以指定包含数据的另一个文件的文件名。如果愿意,
    --     可以使用一个命令行参数覆盖这个INFILE语句。要当心,命令行选项总会覆盖控制文件设置。
    -- *(03) INTO TABLE DEPT:这会告诉SQLLDR要把数据加载到哪个表中(在这个例子中,数据要加载到DEPT表)。
    -- *(04) FIELDS TERMINATED BY ',':这会告诉SQLLDR数据的形式应该是用逗号分隔的值。为SQLLDR描述输入数据的方式有数十种;这只是其中较为常用的方法之一。
    -- *(05) DEPTNO, DNAME, LOC:这会告诉SQLLDR所要加载的列、这些列在输入数据中的顺序以及数据类型。这是指输入流中数据的数据类型,而不是数据库中的数据类型。
    --     在这个例子中,列的数据类型默认为CHAR(255),这已经足够了。
    -- *(06) BEGINDATA:这会告诉SQLLDR你已经完成对输入数据的描述,后面的行(第7~10行)是要加载到DEPT表的具体数据。......-- 这个控制文件采用了最简单、最常用的格式之一:将定界数据加载到一个表。这一章还会看到一些复杂的例子,不过可以从这个简单的控制文件入手,这是一个不错的起点。
    -- 要使用这个控制文件(名为demo1.ctl),只需创建一个空的DEPT表:create table dept
    ( deptno number(2) constraint dpet_pk primary key,
      dname  varchar2(14),
      loc    varchar2(13)
    )
    /-- 并运行以下命令:sqlldr userid=/ control=demo1.ctl-- sqlldr eygle/eygle control=demo1.ctl-- 如果表非空,就会收到一个错误消息:SQL*Loader-601:  对于 INSERT 选项, 表必须为空。表 DEPT 上出错-- 这是因为:这个控制文件中几乎所有选项都取默认值,而默认的加载选项是INSERT(而不是APPEND、TRUNCATE或REPLACE)。要执行INSERT,SQLLDR就认为表为空。
    -- 如果想向DEPT表中增加记录,可以指定加载选项为APPEND;或者,为了替换DEPT表中的数据,可以使用REPLACE或TRUNCATE。REPLACE使用一种传统DELETE语句;因此,
    -- 如果要加载的表中已经包含许多记录,这个操作可能执行得很慢。TRUNCATE则不同,它使用TRUNCATE SQL命令,通常会更快地执行,因为它不必物理地删除每一行。-- 15.1.1 用SQLLDR加载数据的FAQ ( P660 )
    -- 现在来回答Oracle数据库中关于用SQLLDR加载数据最常问到的一些问题。-- *1) 如果加载定界数据?
    -- 定界数据(delimited data)即用某个特殊字符分隔的数据,可能用引号括起,这是当前平面文件最常见的数据格式。在大型机上,定长、固定格式的文件可能是最可识别的文件格式,
    -- 但是在UNIX和NT上,定界文件才是“标准”。在这一节中,我们将分析用于加载定界数据的常用选项。-- 对于定界数据,最常用的格式是逗号分隔值(comma-separated values, CSV)格式。采用这种文件格式,数据中的每个字段与下一个字段用一个逗号分隔。文本串可以用引号括起,
    -- 这样就允许串本身包含逗号。如果串还必须包含引号,一般约定是使用两个引号(在下面的代码中,我们将使用" "而不是' ')。要加载定界数据,
    -- 相应的典型控制文件与前面第一个例子很相似,但是FIELDS TERMINATED BY子句通常如下指定:
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'-- 它指定用逗号分隔数据字段,每个字段可以用双引号括起。如果我们把这个控制文件的最后部分修改如下:
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    (DEPTNO, DNAME, LOC )
    BEGINDATA
    10,Sales,"Virginia,USA"
    20,Accounting,"Va,""USA"""
    30,Consulting,Virginia
    40,Finance,Virginia-- 使用这个控制文件运行SQLLDR时,结果如下:
    eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC
    ---------- ---------------------------- --------------------------
            10 Sales                        Virginia,USA
            20 Accounting                   Va,"USA"
            30 Consulting                   Virginia
            40 Finance                      Virginia-- 要特别注意以下几点:
    -- *(01) 部门10中的Virginia,USA:这是因为输出数据是"Virginia,USA"。输入数据字段必须包括在引号里才能保留数据中的逗号。否则,
    --     数据中的这个逗号会被认为是字段结束标记,这样就会只加载Virginia,而没有USA文本。
    -- *(02) Va, "USA":这是因为输入数据是"Va, ""USA"""。对于引号括起的串,SQLLDR会把其中"的两次出现计为一次出现。
    --     要加载一个包含可选包围字符(enclosure character)的串,必须保证这个包围字符出现两次。-- 另一种常用的格式是制表符定界数据(tag-delimited data),这是用制表符分隔而不是逗号分隔的数据。有两种方法使用TERMINATED BY子句来加载这种数据:
    -- *(01) TERMINATED BY X'09' (使用十六进制格式 的制表符:采用ASCII时,制表符为9)
    -- *(02) TERMINATED BY WHITESPACE-- 这两种方法在实现上有很大差异,下面将会说明。还是用前面的DEPT表,我们将使用以下控制文件加载这个表:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY WHITESPACE
    (DEPTNO, DNAME, LOC)
    BEGINDATA
    10 Sales Virgina-- 从字面上不太容易看得出来,不过要知道,在这里各部分数据之间都有两个制表符。这里的数据行实际上是:
    10\t\tSales\t\tVirginia-- 在此\t
     普遍可识别的制表符转义字符。使用这个控制文件时(包含如前所示的TERMINATED BY WHITESPACE),表DEPT中的数据将是:
    eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC
    ---------- ---------------------------- --------------------------
            10 Sales                        Virgina-- TERMINATED BY WHITESPACE会解析这个串,查询空白符(制表符、空格或换行符)的第一次出现,然后继续查询,直至找到下一个非空白符。因此,解析数据时,
    -- DEPTNO会赋给10,后面的两个制表符被认为是空白符,Sales会赋给DNAME等。-- 另一方面,如果要使用FIELDS TERMINATED BY X'09',如以下控制文件所示,这里稍做修改:LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY X'09'
    (DEPTNO, DNAME, LOC)
    BEGINDATA
    10 Sales Virgina-- 可以看到DEPT中加载了以下数据:
    eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC
    ---------- ---------------------------- --------------------------
            10                              Sales-- 在此,一旦SQLLDR遇到一个制表符,就会输出一个值。因此,将10赋给DEPTNO,DNAME得到了NULL,因为在第一个制表符和制表符的下一次出现之间没有数据。Sales赋给了LOC。-- 这是TERMINATED BY WHITESPACE和TERMINATED BY <character>的有意行为。至于使用哪一种方法更合适,这取决于输入数据以及你要如何解释输入数据。......-- 最后,加载这样的定界数据时,很可能想跳过输入记录中的某些列。例如,你可能想加载字段1、3和5,而跳过第2列和第4列。为此,SQLLDR提供了FILLER关键字。
    -- 这允许你映射一个输入记录中的一列,但不把它放在数据库中。例如,给定DEPT表以及先前的最后一个控制文件,可以修改这个控制文件,使用FILLER关键字正确地加载数据(跳过制表符):LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY X'09'
    (DEPTNO, dummy1 filler, DNAME, dummy2 filler, LOC)
    BEGINDATA
    10 Sales Virgina-- 所得到的表DEPT现在如下所示:eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC
    ---------- ---------------------------- --------------------------
            10 Sales                        Virgina-- *2) 如何加载固定格式数据? ( P662 )
    -- 通常会有一个由某个外部系统生成的平面文件,而且这是一个定长文件,其中包含着固定位置的数据(positional data)。
    -- 例如,NAME字段位于第1~10字节,ADDRESS字段位于第11~35字节等。我们将介绍SQLLDR如何为我们导入这种数据。-- 这种定宽的固定位置数据是最适合SQLLDR加载的数据格式。要加载这种数据,使用SQLLDR是最快的处理方法,因为解析输入数据流相当容易。
    -- SQLLDR会在数据记录中存储固定字符偏移量和长度,因此抽取某个给定字段相当简单。如果要加载大量数据,将其转换为一种固定位置格式通常是最好的办法。当然,
    -- 定宽文件也有一个缺点,它比简单的定界文件格式可能要大得多。-- 要加载定宽的固定位置数据,将会在控制文件中使用POSITION关键字,例如:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    ( DEPTNO position(1:2),
      DNAME  position(3:16),
      LOC    position(17:29)
    )
    BEGINDATA
    10Accounting    Virginia,USA-- 这个控制文件没有使用FIELDS TERMINATED BY子句;而是使用了POSITION来告诉SQLLDR字段从哪里开始,到哪里结束。关于POSITION子句有意思的是,我们可以使用重叠的位置,
    -- 可以在记录中来回反复。例如,如果如下修改DEPT表:alter table dept add entire_line varchar(29);-- 并使用以下控制文件:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    ( DEPTNO  position(1:2),
      DNAME   position(3:16),
      LOC     position(17:29),
      ENTIRE_LINE position(1:29)
    )
    BEGINDATA
    10Accounting    Virginia,USA-- 字段ENTIRE_LINE定义为POSITION(1:29)。这会从所有29字节的输入中抽取出这个字段的数据,而其他字段都是输入数据的子串。这个控制文件的输出如下:eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        ENTIRE_LINE
    ---------- ---------------------------- -------------------------- ----------------------------------------------------------
            10 Accounting                   Virginia,USA               10Accounting    Virginia,USA-- 使用POSITION时,可以使用相对偏移量,也可以使用绝对偏移量。在前面的例子中使用了绝对偏移量,我们明确地指示了字段从哪里开始,到哪里结束。也可以把前面的控制文件写作:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    ( DEPTNO      position(1:2),
      DNAME       position(*:16),
      LOC         position(*:29),
      ENTIRE_LINE position(1:29)
    )
    BEGINDATA
    10Accounting    Virginia,USA-- *指控制文件得出上一个字段在哪里结束。因此,在这种情况下,(*:16)与(3:16)是一样的。注意,控制文件中可以混合使用相对位置和绝对位置。另外。
    -- 使用*表示法时,可以把它与偏移量相加。例如,如果DNAME从DEPTNO结束之后第2个字节处开始,可以使用(*+2:16)。-- POSITION子句中的结束位置必须是数据结束的绝对列位置。有时,可能指定每个字段的长度更为容易,特别是如果这些字段是连续的(就像前面的例子一样)。
    -- 采用这种方式,只需告诉SQLLDR:记录从第1个字节开始,然后指定每个字段的长度就行了。这样我们就可以免于计算记录中的开始和结束偏移量,这个计算有时可能很困难。
    -- 为此,可以不指定结束位置,而是指定定长记录中的各个字段的长度,如下:
    LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    ( DEPTNO      position(1) char(2),
      DNAME       position(*) char(14),
      LOC         position(*) char(13),
      ENTIRE_LINE position(1) char(29)
    )
    BEGINDATA
    10Accounting    Virginia,USA-- 在此只需告诉SQLLDR第一个字段从哪里开始及其长度。后面的每个字段都从上一个字段结束处开始,并具有指定的长度。直至最后一个字段才需要再次指定位置,
    -- 因为这个字段又要从记录起始处开始。
      

  3.   

    -- *4) 如果使用函数加载数据? ( P666 )
    -- 在这一节中,我们将介绍加载数据时如何使用函数-- 一旦你了解了SQLLDR如何构建其INSERT语句,在SQLLDR中使用函数就很容易了。要在SQLLDR脚本中向某个字段应用一个函数,只需将这个函数增加到控制文件中(用两个引号括起)。
    -- 例如,假设有前面的DEPT表,你想确保所加载的数据都是大写的。可以使用以下控制文件来加载:LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY ','
    ( DEPTNO,
      DNAME  "upper(:dname)",
      LOC    "upper(:loc)",
      LAST_UPDATED date 'dd/mm/yyyy'
    )
    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-- 数据库中得到的数据如下:eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        LAST_UPDATED
    ---------- ---------------------------- -------------------------- -------------------
            10 SALES                        VIRGINIA                   2000-05-01 00:00:00
            20 ACCOUNTING                   VIRGINIA                   1999-06-21 00:00:00
            30 CONSULTING                   VIRGINIA                   2000-01-05 00:00:00
            40 FINANCE                      VIRGINIA                   2001-03-15 00:00:00-- 可以注意到,只需向一个绑定变量应用UPPER函数就可以很容易地将数据变为大写。要注意,SQL函数可以引用任何列,而不论将函数实际上应用于哪个列。这说明,
    -- 一个列可以是对两个或更多其他列应用一个函数的结果。例如,如果你想加载ENTIRE_LINE列,可以使用SQL连接运算符。不过,这种情况下这样做稍有些麻烦。现在,
    -- 输入数据集中有4个数据元素。如果只是向控制文件中如下增加ENTIRE_LINE:LOAD DATA
    INFILE *
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY ','
    ( 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-- 就会看到,日志文件中对于每个输入记录出现以下错误:
    Record 1: Rejected - Error on table DEPT, column ENTIRE_LINE.
    Column not found before end of logical record (use TRAILING NULLCOLS)记录 1: 被拒绝 - 表 DEPT 的列 ENTIRE_LINE 出现错误。
    在逻辑记录结束之前未找到列 (使用 TRAILING NULLCOLS)-- 在此,SQLLDR告诉你:没等处理完所有列,记录中就没有数据了。这种情况下,解决方案很简单。实际上,SQLLDR甚至已经告诉了我们该怎么做:这就是使用TRAILING NULLCOLS。
    -- 这样一来,如果输入记录中不存在某一列的数据,SQLLDR就会为该列绑定一个NULL值。在这种情况下,增加TRAILING NULLCOLS会导致绑定变量:ENTIRE_LINE成为NULL。
    -- 所以再尝试这个控制文件: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-- 现在表中的数据如下:eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        LAST_UPDATED        ENTIRE_LINE
    ---------- ---------------------------- -------------------------- ------------------- ----------------------------------------------------------
            10 SALES                        VIRGINIA                   2000-05-01 00:00:00 10SalesVirginia1/5/2000
            20 ACCOUNTING                   VIRGINIA                   1999-06-21 00:00:00 20AccountingVirginia21/6/1999
            30 CONSULTING                   VIRGINIA                   2000-01-05 00:00:00 30ConsultingVirginia5/1/2000
            40 FINANCE                      VIRGINIA                   2001-03-15 00:00:00 40FinanceVirginia15/3/2001-- 之所以可以这样做,原因在于SQLLDR构建其INSERT语句的做法。SQLLDR会查看前面的控制文件,并看到控制文件中的DEPTNO、DNAME、LOC、LAST_UPDATED和ENTIRE_LINE这几列。
    -- 它会根据这些列建立5个绑定变量。通常,如果没有任何函数,所建立的INSERT语句就是:
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE )
    VALUES ( :DEPTNO, :DNAME, :LOC, :LAST_UPDATED, :ENTIRE_LINE );-- 然后再解析输入流,将值赋给相应的绑定变量,然后执行语句。如果使用函数,SQLLDR会把这些函数结合到INSERT语句中。在上一个例子中,SQLLDR建立的INSERT语句如下所示:
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC, LAST_UPDATED, ENTIRE_LINE )
    VALUES ( :DEPTNO, upper(:dname), upper(:loc), :last_updated, 
             :deptno||:dname||:loc||:last_updated );-- 然后再做好准备,把输入绑定到这个语句,再执行语句。所以,SQL中能做的事情都可以结合到SQLLDR脚本中。由于SQL中增加了CASE语句,所以这样做不仅功能极为强大,
    -- 而且相当容易。例如,假设你的输入文件有以下格式的日期:-- *(01) HH24:MI:SS:只有一个时间;日期默认为SYSDATE。
    -- *(02) DD/MM/YYYY:只有一个日期;时间默认为午夜0点。
    -- *(03) HH24:MI:SS DD/MM/YYYY:日期和时间都要显式提供。-- 可以使用如下的一个控制文件: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-- 可以得到以下结果:
    eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        LAST_UPDATED
    ---------- ---------------------------- -------------------------- -------------------
            10 SALES                        VIRGINIA                   2005-10-17 12:03:03
            20 ACCOUNTING                   VIRGINIA                   2011-03-01 02:23:54
            30 CONSULTING                   VIRGINIA                   2005-10-21 01:24:00
            40 FINANCE                      VIRGINIA                   2005-08-17 00:00:00-- 现在向输入字符应用3个日期格式中的一个(注意,这里不再加载一个DATE;而只是加载一个串)。CASE函数会查看串的长度和内容,从而确定应该使用哪一个掩码。-- 有意思的是,你可以编写自己的函数来由SQLLDR调用。这直接应验了可以从SQL调用PL/SQL。
      

  4.   

    谢谢 luoyoumou 的回复,
    但是我没有找到答案,
    我不想在控制文件中指定日期的格式 ,我想让sqlloader 自已去识别,
    因为,我的控制文件是程序自己动生成的。
      

  5.   


    -- 还有:程序能够自己生成控制文件,就不能在date类型的字段指定其格式?
      

  6.   

    就如insert 记录时,
    如果我  alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'
    那在insert时,就不要转类型了。
      

  7.   

    -- 那只是对当前的会话有用!
    -- 但是记住:SQLLDR是一个命令行工具(也就是说,这是一个单独的程序)。它并非一个API,例如,不能“从PL/SQL调用”。
      

  8.   

    永久性设置,只能用控制文件,或自定义一个日期格式的函数,然后在导入时,调用此函数!-- 想都别去想:alter session set nls_date_format=......
    -- 其原因:我上面已经说清楚啦!
      

  9.   

    -- sqlldr 加载示例:
    -- *1) 假设你有一个用户 eygle,其密码也为 eygle
    -- *2) 假设用户eygle下有表dept,建表代码如下:
      CREATE TABLE "EYGLE"."DEPT"
       (    "DEPTNO" NUMBER(2,0),
            "DNAME" VARCHAR2(14),
            "LOC" VARCHAR2(13),
            "LAST_UPDATED" DATE
       );-- *3) 在c盘根目录下创建名为sqlldr.ctl的控制文件,其内容如下:(因为你的文件没有扩展名,所以 INFILE 'c:\dept_data.',在文件名后面加个句点就可以啦)
    LOAD DATA
    INFILE 'c:\dept_data.'
    INTO TABLE DEPT
    REPLACE
    FIELDS TERMINATED BY ','
    ( DEPTNO,
      DNAME,
      LOC,
      LAST_UPDATED date 'dd/mm/yyyy'
    )-- *4) 在c盘根目录下创建名为 dept_data (没有扩展名) 的数据文件,内容如下:
    10,Sales,Virginia,1/5/2000
    20,Accounting,Virginia,21/6/1999
    30,Consulting,Virginia,5/1/2000
    40,Finance,Virginia,15/3/2001-- *5) 执行导入数据:
    C:\>sqlldr eygle/eygle control=c:\sqlldr.ctlSQL*Loader: Release 10.2.0.1.0 - Production on 星期四 3月 31 15:18:20 2011Copyright (c) 1982, 2005, Oracle.  All rights reserved.达到提交点 - 逻辑记录计数 3
    达到提交点 - 逻辑记录计数 4-- *6) 验证表中数据是否成功导入!eygle@SZTYORA> select * from dept;    DEPTNO DNAME                        LOC                        LAST_UPDATED
    ---------- ---------------------------- -------------------------- -------------------
            10 Sales                        Virginia                   2000-05-01 00:00:00
            20 Accounting                   Virginia                   1999-06-21 00:00:00
            30 Consulting                   Virginia                   2000-01-05 00:00:00
            40 Finance                      Virginia                   2001-03-15 00:00:00
      

  10.   

    SQL*Loader-500: Unable to open file (/*****/tmp/R3685184918871_resultA.)加了点,好像不行
      

  11.   


    你给出的代码,只在window平台有效,到 solaris或AIX 下不行了
      

  12.   

    luoyoumou,你的例子教程从哪看的,有没有个链接地址啊啥的?