Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle-.CSV文件一次复制到多个表_Oracle_Csv_Plsql_Bulk Collect - Fatal编程技术网

Oracle-.CSV文件一次复制到多个表

Oracle-.CSV文件一次复制到多个表,oracle,csv,plsql,bulk-collect,Oracle,Csv,Plsql,Bulk Collect,我必须将.CSV文件加载到我的Oracle表中。但问题是,单个CSV文件将包含多个表的数据。诀窍是我们需要识别要插入到特定表中的第一列数据。i、 e.如果第一列的值为“16”,则应将整行插入表_16,表_16将有16列,如果值为21,表_21将有21列,依此类推。还有一点要注意的是,我的CSV文件将有数百万条记录,所以我也需要考虑这个过程的性能,所以我认为批量收集< /代码>和代码> For ALL/将是最好的插入数据的方法。 当我尝试运行以下程序块时,出现以下错误: 01403。00000-“

我必须将.CSV文件加载到我的Oracle表中。但问题是,单个CSV文件将包含多个表的数据。诀窍是我们需要识别要插入到特定表中的第一列数据。i、 e.如果第一列的值为“16”,则应将整行插入表_16,表_16将有16列,如果值为21,表_21将有21列,依此类推。还有一点要注意的是,我的CSV文件将有数百万条记录,所以我也需要考虑这个过程的性能,所以我认为<代码>批量收集< /代码>和<>代码> For ALL/<代码>将是最好的插入数据的方法。 当我尝试运行以下程序块时,出现以下错误:

01403。00000-“未找到任何数据”
*原因:未从对象中找到任何数据。
*操作:可能由于提取结束,没有来自对象的数据。


示例.CSV数据

16,"Laura","Bissot","LBISSOT","650.124.5234",20-08-05,"ST_CLERK",3300,,121,50,"aaa",234,"asdf","ssedf","wsdrftd"
21,"Mozhe","Atkinson","MATKINSO","650.124.6234",30-10-05,"ST_CLERK",2800,,121,50,"aaa",234,"asdf","ssedf","wsdrftd","aaa",234,"asdf","ssedf","wsdrftd"
11,"James","Marlow","JAMRLOW","650.124.7234",16-02-05,"ST_CLERK",2500,,121,50
16,"TJ","Olson","TJOLSON","650.124.8234",10-04-07,"ST_CLERK",2100,,121,50,"aaa",234,"asdf","ssedf","wsdrftd"
19,"Jason","Mallin","JMALLIN","650.127.1934",14-06-04,"ST_CLERK",3300,,122,50,"aaa",234,"asdf","ssedf","wsdrftd","aaa",234,"asdf",
12,"Michael","Rogers","MROGERS","650.127.1834",26-08-06,"ST_CLERK",2900,,122,50,"aaa"
14,"Ki","Gee","KGEE","650.127.1734",12-12-07,"ST_CLERK",2400,,122,50,"aaa",234,"asdf"
30,"Ki","Gee","KGEE","650.127.1734",12-12-07,"ST_CLERK",2400,,122,50,"aaa",234,"asdf",11,"dd",23,43,789,9086,"1DRFtf","PST","RTF%$",123,"dsda",5656,"dsed",123,4333,112

创建或替换类型
T_CSV_数据作为对象
(c001 varchar2(50)、c002 varchar2(150)、c003 varchar2(150)、c004 varchar2(150)、c005 varchar2(150)、c006 varchar2(150)、c007 varchar2(150)、c008 varchar2(150)、c009 varchar2(150)、c010 varchar2(150),
c011 varchar2(150)、c012 varchar2(150)、c013 varchar2(150)、c014 varchar2(150)、c015 varchar2(150)、c016 varchar2(150)、c017 varchar2(150)、c018 varchar2(150)、c019 varchar2(150)、c020 varchar2(150),
c021 varchar2(150)、c022 varchar2(150)、c023 varchar2(150)、c024 varchar2(150)、c025 varchar2(150)、c026 varchar2(150)、c027 varchar2(150)、c028 varchar2(150)、c029 varchar2(150)、c030 varchar2(150));
创建或替换类型T_CSV_VAL作为T_CSV_数据表;
声明
--用于将blob复制到clob中的变量
v_blob blob;
v_clob clob;
v_dest_偏移整数:=1;
v_src_偏移整数:=1;
v_lang_context INTEGER:=dbms_lob.default_lang_ctx;
v_警告整数;
--与迭代clob的每一行有关的变量
v_新线_位置编号;
v_开始位置编号:=1;
v_电流_线VARCHAR2(4000);
v_总长度数;
v_curr_row apex_application_global.vc_arr2;
V_DATA_ASSIGN T_CSV_VAL:=T_CSV_VAL();
V_BULK_DATA T_CSV_VAL:=T_CSV_VAL();
开始--t_csv_行
从ID=7的FILE_UPLOAD中将FILE_BLOB选择为v_BLOB;
dbms_lob.createtemporary(v_clob,true);
dbms_lob.converttoclob(dest_lob=>v_clob,src_blob=>v_blob,amount=>dbms_lob.lobmaxsize,dest_offset=>v_dest_offset,src_offset
=>v_src_offset,blob_csid=>dbms_lob.default_csid,lang_context=>v_lang_context,warning=>v_warning);
v_total_len:=dbms_lob.getlength(v_clob);

而(v_start_pos我认为最简单的解决方案是首先使用Shell脚本/SQL加载器将所有数据转储到预暂存表中。 一旦将数据转储到预暂存中,就可以编写PLSQL块/包,将特定行插入到所需的表中

在PLSQL块中,您可以使用批量收集来最大限度地提高性能

谢谢,
Idrees

在我看来,您走错了路。您倾向使用的PL/SQL无法击败SQL*Loader,尤其是在启用直接路径和并行执行时

下面是一个简单的例子,说明了如何做到这一点

创建表:我太懒了,无法创建16列或21列的表,所以我使用4列(
t1
)和5列(
t1

控制文件:

options (direct=true, parallel=true)
load data 
infile *

into table t1
  append
  when (1) = '4'
  fields terminated by ',' optionally enclosed by '"'
  trailing nullcols  
  (
  id position(1) integer external, 
  fname char,
  lname char,
  salary integer external
  )

into table t2
  append
  when (1) = '5'
  fields terminated by ',' optionally enclosed by '"'
  trailing nullcols
  (
  id position (1) integer external, 
  fname char,
  lname char,
  salary integer external,
  hiredate "to_date(:hiredate, 'dd-mm-rr')"
  )

begindata
4,"Laura","Bissot",6506,14-06-04
5,"Mozhe","Atkinson",1202,20-08-05
5,"James","Marlow",1244,30-10-05
4,"TJ","Olson",4345,16-02-05
正在加载会话&结果:

SQL> $sqlldr scott/tiger control=test05.ctl log=test05.log

SQL*Loader: Release 11.2.0.2.0 - Production on Pon Kol 27 15:21:17 2018

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.


Load completed - logical record count 4.

SQL> select * From t1;

        ID FNAME                LNAME                    SALARY
---------- -------------------- -------------------- ----------
         4 Laura                Bissot                     6506
         4 TJ                   Olson                      4345

SQL> select * From t2;

        ID FNAME                LNAME                    SALARY HIREDATE
---------- -------------------- -------------------- ---------- ----------
         5 Mozhe                Atkinson                   1202 20/08/2005
         5 James                Marlow                     1244 30/10/2005

SQL>

我同意@Littlefoot SQL Loader是一种自然而快速的方法。
另一种选择是使用Oracle的“外部表”

使用此选项,您可以对驻留在操作系统(OS)文件系统上的文件使用SELECT语句。
例如,CSV格式的文本文件

书籍:数据库实用程序Chaepter:外部 桌子
外部表功能是对现有SQLLoader的补充 功能。它使您能够访问外部源中的数据,就像 它在数据库的一个表中。
请注意,SQLLoader可能是 在需要额外资源的数据加载情况下有更好的选择 临时表的索引

基本步骤:

1-在运行Oracle实例的操作系统(OS)的文件系统中创建一个子目录。
例如: 如果操作系统是Windows,则在单元“C:”上的子目录“DATA”内创建子目录“IN_FILES”:

如果操作系统是Linux/Unix,那么在根目录的子目录“data”中创建一个子目录“in_files”

2-在操作系统上,为运行Oracle实例的操作系统用户授予子目录步骤(1)的读写权限

3-在Oracle上创建目录对象
您可以根据文件系统的规则使用完整路径。
如果操作系统是Windows,则完整路径类似于“C:\DATA\IN\u FILES”

如果操作系统是Linux/Unix,那么完整路径类似于“/data/in_files”

4-Oracle向公众授予步骤3中目录对象的读/写权限

向公众授予对目录外部信息的读、写权限

5-创建外部表格以访问CSV文件:

在本例中,文件为:
a、 CSV格式
b、 记录的结尾是回车,后面是换行符(
记录以“\r\n”分隔)

c、 第一条记录是标题列名,(
跳过1

d、 字段分隔符是逗号(
字段以“,”结尾

e、 数据可以用引号括起来(ASCII字符34)(
也可以用''
括起来)
f、 缺少的字段将具有空值(
缺少的字段值为空

g、 文件名为“data01.csv”,此名称符合操作系统规则
记住Windows不区分大小写,但LINUX/Unix区分大小写

create table data01_external
  (id       number,
   fname    varchar2(20),
   lname    varchar2(20),
   salary   number,
   hiredate date
  )
  organization external
  (type oracle_loader
   default directory external_info
   access parameters (records delimited by '\r\n'
                      badfile     'data01_%p.bad'
                      discardfile 'data01_%p.dis'
                      logfile     'data01_%p.log'
                      skip 1
                      fields terminated by ','
                             optionally enclosed by '"'
                             missing field values are null
                      (id        integer external,
                       fname     char,
                       lname     char,
                       salary    decimal external,
                       hiredate  char  date_format date mask 'dd-mm-rr'
                      )
                     )
   location ('data01.csv')
  )
  reject limit UNLIMITED;
6-现在您可以编写一个PL/SQL包来插入
SQL> $sqlldr scott/tiger control=test05.ctl log=test05.log

SQL*Loader: Release 11.2.0.2.0 - Production on Pon Kol 27 15:21:17 2018

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.


Load completed - logical record count 4.

SQL> select * From t1;

        ID FNAME                LNAME                    SALARY
---------- -------------------- -------------------- ----------
         4 Laura                Bissot                     6506
         4 TJ                   Olson                      4345

SQL> select * From t2;

        ID FNAME                LNAME                    SALARY HIREDATE
---------- -------------------- -------------------- ---------- ----------
         5 Mozhe                Atkinson                   1202 20/08/2005
         5 James                Marlow                     1244 30/10/2005

SQL>
Create directory external_info as 'C:\DATA\IN_FILES'
Create directory external_info as '/data/in_files'
create table data01_external
  (id       number,
   fname    varchar2(20),
   lname    varchar2(20),
   salary   number,
   hiredate date
  )
  organization external
  (type oracle_loader
   default directory external_info
   access parameters (records delimited by '\r\n'
                      badfile     'data01_%p.bad'
                      discardfile 'data01_%p.dis'
                      logfile     'data01_%p.log'
                      skip 1
                      fields terminated by ','
                             optionally enclosed by '"'
                             missing field values are null
                      (id        integer external,
                       fname     char,
                       lname     char,
                       salary    decimal external,
                       hiredate  char  date_format date mask 'dd-mm-rr'
                      )
                     )
   location ('data01.csv')
  )
  reject limit UNLIMITED;
Create or replace package pk_load_info
  is
    procedure pr_load(p_isbFile_name     varchar2,
                      p_onuErrCode   out number,
                      p_osbErrDesc   out varchar2
                     );
End;
/


Create or replace package body pk_load_info
is
  procedure pr_load(p_isbFile_name     varchar2,
                    p_onuErrCode   out number,
                    p_osbErrDesc    out varchar2
                   )
  is
    sbEvent    varchar2(20);
    sbSentence varchar2(200);
  Begin
    p_onuErrCode:=0;
    p_osbErrDesc:=null;
    --
    if trim(p_isbFile_name) is null then
       p_onuErrCode:=101;
       p_osbErrDesc:='The name of the file is not to be null';
       return;
    End if;
    --
    -- you can use always the same file name of maybe use different file name in every run.
    sbEvent:='alter table';
    sbSentence:='alter table data01_external default directory EXTERNAL_INFO location ('||chr(39)||trim(p_isbFile_name)||chr(39)||')';
    Dbms_Output.Put_Line('sbSentence='||sbSentence);
    execute immediate sbSentence;
    --
    -- hint "append", in direct-path INSERT, data is appended to the end of the table
    sbEvent:='insert table T1';
    insert /*+ append */ into t1
    select a.id,
           a.fname,
           a.lname,
           a.salary
    from data01_external a
    where a.id=4;
    --
    sbEvent:='insert table T2';
    insert /*+ append */ into t2
    select a.id,
           a.fname,
           a.lname,
           a.salary,
           hiredate
    from data01_external a
    where a.id=5;
  Exception
    when others then
         p_onuErrCode:=sqlcode;
         p_osbErrDesc:='Event "'||sbEvent||'" '||sqlerrm;
  End pr_load;
End pk_load_info;
/
ID,FNAME,LNAME,SALARY,HIREDATE
4,"Laura","Bissot",6506
5,"Mozhe","Atkinson",1202,20-08-05
5,"James","Marlow",1244,30-10-05
4,"TJ","Olson",4345
Declare
  nuErrcode      number;
  sbErrdesc      varchar2(2000);
  Procedure print(p_isbTexto varchar2)
  is
  Begin
    if nvl(length(p_isbTexto),0)<=255 then
       dbms_output.put_line(p_isbTexto);
    Else
       dbms_output.put_line(substr(p_isbTexto,1,254)||'¬');
       dbms_output.put_line(substr(p_isbTexto,255,255));
    End if;
  End print;
Begin
  print(to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss.ff4')||'|Begin');
  dbms_application_info.set_module('SQL','Inicio');
  --
  pk_load_info.pr_load('data02.csv',
                       nuErrcode,
                       sbErrdesc
                      );
  print('nuErrcode='||nuErrcode);
  print('sbErrdesc='||sbErrdesc);
  --
  if nuErrcode=0 then
     commit;
  Else
     rollback;
  end if;
  print(to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss.ff4')||'|End');
  dbms_application_info.set_action('Fin');
End;
/
select *
from t1;
ID|FNAME|LNAME |SALARY|
 4|Laura|Bissot|6506  |
 4|TJ   |Olson |4345  |

select *
from t2;
ID|FNAME|LNAME   |SALARY|HIREDATE           |
5 |Mozhe|Atkinson|  1202|2005-08-20 00:00:00|
5 |James|Marlow  |  1244|2005-10-30 00:00:00|