【问题标题】:Inserting million of records into a file [closed]将数百万条记录插入文件[关闭]
【发布时间】:2013-12-23 16:19:23
【问题描述】:

我想使用 oracle 将数百万条记录插入文件中,而不使用循环或 java 代码。

在浏览时,我在 oracle 中发现了一些 util_file,它用于将行记录到文件中,但无法使用它。可以请一些人帮助我理解或编写代码以将选择查询返回的结果集写入文件,甚至程序甚至可以工作。

我尝试了以下程序,它成功运行但没有创建包含数据的文件

  create or replace procedure familydetails 
       ( p_file_dir IN varchar2, p_filename IN varchar2 ) 
      IS v_filehandle utl_file.file_type; 
       cursor family Is  
       select * from fmly_detl  
       begin 
       v_filehandle :=utl_file.fopen('C:\tempfolder','sqltest.txt','W'); 
       utl_file.new_line(v_filehandle); 
       for fmly IN fmly_detl LOOP 
       utl_file.putf(v_filehandle,'family %s details:s\n',fmly.last_name,fmly.first_name,fmly.indv_id);   
       end loop;
      utl_file.put_line(v_filehandle,'END OF REPORT'); 
       UTL_FILE.fclose(v_filehandle); 
       end familydetails;

【问题讨论】:

  • 您有什么可能的理由来禁止使用循环?如果要写入文件,则需要过程代码。程序代码使用循环。
  • 我不想写一个循环,因为选择查询会返回超过 1000 万条记录,如果我写一个循环,我想加快处理速度,然后必须一一重复所有超过 1000 万条记录并插入到文件中,这是我第一次使用程序,所以我不确定它们是如何工作的,抱歉,但据我所知,我认为与带有循环的 sql 将其写入文件相比,程序的性能会更快,如果我错了,请纠正我
  • 您为什么无法使用utl_file?如果您对使用该代码编写的代码有特定问题,请将您的代码和错误添加到问题中。您将如何以及在何处调用此过程?该文件将在服务器上还是在客户端上?数据将采用什么格式?
  • @user3124277 - 将 1000 万行数据写入平面文件会相对较慢。如果您想在 PL/SQL 中执行此操作,您将需要一个遍历所有行的循环。您可以在循环中 BULK COLLECT 数据(使用 LIMIT)使事情变得更快,但我几乎可以保证上下文转换不会占您处理时间的很大一部分。
  • 无论您使用的是 SQL、PL/SQL 还是 Java,数据都会从 DB 读取到缓冲区中;您可以调整数组大小来调整它。无论您是使用utl_file 还是Java 将数据写出,数据都将写入缓冲区中的磁盘。您似乎过早地进行了优化。如果你不理解你已经看过的utl_file 的例子,如果有人在这里再试一次,你会明白吗?我们无法为您编写符合您规范的程序,您必须付出一些努力,否则您将无法理解或学习。

标签: oracle stored-procedures procedure


【解决方案1】:

1)如果你在unix中使用sqlplus..这里有一个简单的解决方案,把下面的作为script_name.ksh并执行它(ksh script_name.ksh)

sqlplus -s user_id/password@sid << ! >> ~/sql_output.txt

set feedback off;
set pages 0;
set linesize 20000;
set arraysize 1000;
set tab  off;
--Your Query, with proper padding , or comma seprated
--Eg Select employee_id||'|'||employee_name||'|'||employee_age
--   from employee;

!

2) 如果您使用像SQL DeveloperTOAD 这样的IDE,您可以执行查询并导出它。

3) 但是对于 PL/SQL

下面提到的

test_dir,是主机中的一个目录,Oracle可以访问。它应该列在 *ALL_DIRECTORIES* 字典表中。

DECLARE
  fileHandler UTL_FILE.FILE_TYPE;
  cursor emp_cursor is select employee_id,employee_name,employee_age FROM employee;
  TYPE emp_type IS TABLE OF emp_cursor%ROWTYPE INDEX BY PLS_INTEGER;

  l_emp_type emp_type;
  v_fetch_limit NUMbER := 10000;
BEGIN
  fileHandler := UTL_FILE.FOPEN('test_dir', 'sql_output.txt', 'W',max_linesize => 4000);
  open emp_cursor;
  LOOP
      FETCH emp_cursor BULK COLLECT INTO l_emp_type LIMIT v_fetch_limit;
      EXIT WHEN l_emp_type.COUNT < v_fetch_limit;
      // Used to control the fetch size.
      FOR I IN 1..l_emp_type.COUNT LOOP
          UTL_FILE.PUTF(fileHandler, '%s|%s|%s',l_emp_type(I).employee_id,
                                               l_emp_type(I).employee_name,
                                               l_emp_type(I).employee_age);
      END LOOP;
      UTL_FILE.FFLUSH(fileHandler);//Flush the buffer to file
  END LOOP
  UTL_FILE.FCLOSE(fileHandler);
  IF(emp_cursor%ISOPEN) THEN
       emp_cursor.close();
  END IF;
EXCEPTION
  WHEN utl_file.invalid_path THEN
     raise_application_error(-20000, 'ERROR: Invalid PATH FOR file.');
     IF(emp_cursor%ISOPEN) THEN
         emp_cursor.close();
     END IF;
END;
/

最后,从 Server 的 UTL_FILE 目录中复制它。 该目录也可能是 NAS 挂载。只是 Oracle 需要对它有写访问权。

4) 像 PL/SQL、Pro*C 程序或任何 OCI 接口一样都可以工作!一般来说,选项 3 和 4 可以让您很好地控制您所做的过程!

祝你好运!

编辑:增加了对获取大小和刷新的改进

【讨论】:

  • 我收到文件 ORA-06512 错误的无效路径
  • 你能做到吗select * from all_directories;
  • 你必须使用那个名字而不是test_dir
  • 你的意思是我必须从 select * from all_directories 查询返回的结果中选择任何目录名
  • 是的,你不能给出完整的路径。oracle 稍后会解决它。
猜你喜欢
  • 2023-01-31
  • 2013-11-10
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
相关资源
最近更新 更多