oracle ebs + PL/SQL实现将查询出来的数据保存为csv格式文件,并定期上传到FTP服务器学习总结

目的
oracle ebs + PL/SQL实现将查询出来的数据保存为csv格式文件,并定期上传到FTP服务器。
用到oracle utl_file包,FTP文件上传
第一次接触这种类型的任务,也是在网上查询了很多参考资料才弄出来。
下面是具体的例子。
先在前台配置请求:系统管理员→并发→程序→定义

系统管理员→并发→程序→定义
系统管理员→并发→程序→可执行
将该请求挂到相应的责任下
挂请求到责任
后台数据库代码
创建包头

create or replace PACKAGE ML_OPCM_INFORMATION_UPLOAD AS
     procedure ML_OPCM_INFORMATION(  
           o_err_code OUT NUMBER,
           o_err_msg OUT VARCHAR2,
           IC_TABLE_NAME in varchar2  ,  -- FTP服务器列表
           IC_ROW_NAME in varchar2  ,  --FTP服务器行名
           IC_FILE_NAME in varchar2   -- 文件名称
     )  ;
END ML_OPCM_INFORMATION_UPLOAD;

包体

create or replace PACKAGE BODY ML_OPCM_INFORMATION_UPLOAD AS

PROCEDURE SEND_OUTPUT(
    ic_output IN VARCHAR2)
AS
BEGIN
  fnd_file.put_line(fnd_file.output, ic_output);
  --dbms_output.put_line (ic_output);
END SEND_OUTPUT;

PROCEDURE SEND_LOG(
    ic_log IN VARCHAR2)
AS
BEGIN
  fnd_file.put_line(fnd_file.log, ic_log);
  --dbms_output.put_line (ic_log);
END SEND_LOG;

procedure ML_OPCM_INFORMATION(  
                  o_err_code OUT NUMBER,
                  o_err_msg OUT VARCHAR2,
                  IC_TABLE_NAME in VARCHAR2  ,  -- FTP服务器列表
                  IC_ROW_NAME in VARCHAR2  ,  --FTP服务器行名
                  IC_FILE_NAME in VARCHAR2   -- 文件名称
)  
is  
    l_conn  UTL_TCP.connection;
    vc_ftp_server_host VARCHAR2(100) :=NULL;  --服务器地址
    vc_ftp_server_port VARCHAR2(10)  :=NULL;  --端口
    vc_ftp_account     VARCHAR2(100) :=NULL;  --用户名
    vc_ftp_password    VARCHAR2(100) :=NULL;  --密码
    l_output           utl_file.file_type;  
    l_theCursor        integer default dbms_sql.open_cursor;  --OPEN_CURSOR: 返回新游标的ID值 
    l_columnValue      VARCHAR2(2000);  
    l_status           integer;  
    l_colCnt           number default 0;  
    l_separator        VARCHAR2(1) ;  
    p_filename         VARCHAR2(50) ;  
    l_cnt              number default 0;  
    p_query            varchar2(4000);  
    l_desctbl          DBMS_SQL.DESC_TAB;
    date_famart        VARCHAR2(10) default 'YYYY-MM-DD'; 

    CURSOR cur_ftp_info(ic_cur_table_name VARCHAR2,ic_cur_row_name VARCHAR2)
    IS
    SELECT put.user_table_name table_name,
      puc.user_column_name column_name,
      purf.row_low_range_or_name row_name,
      pucif.VALUE p_value
    FROM pay_user_tables put,
      pay_user_columns puc,
      pay_user_rows_f purf,
      pay_user_column_instances_f pucif
    WHERE put.user_table_id        = puc.user_table_id
    AND put.user_table_id          = purf.user_table_id
    AND pucif.user_row_id          = purf.user_row_id
    AND pucif.user_column_id       = puc.user_column_id
    AND purf.row_low_range_or_name = ic_cur_row_name
    AND put.user_table_name        = ic_cur_table_name ;

begin  
    p_filename := 'TERMINATION_EMP.CSV';  
-- 先要创建路径 create or replace directory UTL_FILE_DIR as '/tmp'; 
    begin 
      l_output := utl_file.fopen('UTL_FILE_DIR', p_filename, 'w');      
    exception 
     when others then
      SEND_LOG('Error when open the file from UTL_FILE_DIR :'||SQLCODE||'-'||SQLERRM);
    end;
    BEGIN
  --p_query定义为varchar2类型,如果超过varchar2最大值可以用clob类型
      p_query :='select *  from emp ';  
     -- DBMS_OUTPUT.PUT_LINE(p_query); 
     --PARSE:解析要执行的语句 
     -- p_query sql语句
      dbms_sql.parse(l_theCursor,  p_query, dbms_sql.native );  
      DBMS_SQL.DESCRIBE_COLUMNS(l_theCursor, l_colCnt, l_desctbl);  
      --DUMP TABLE COLUMN NAME  
      FOR I IN 1 .. l_colCnt LOOP  
        UTL_FILE.PUT(l_output,l_separator || l_desctbl(I).COL_NAME ); --输出表字段  
        DBMS_SQL.DEFINE_COLUMN(l_theCursor, I, l_columnValue, 4000);  --DEFINE_COLOUMN:定义字段变量,其值对应于指定游标中某个位置元素的值
        l_separator := ',';  
      END LOOP;  
      --记事本打开会换行 chr(13),chr(10)分别对应\r,\n
      UTL_FILE.put(l_output,chr(13)||chr(10));
      UTL_FILE.NEW_LINE(l_output,0);
      --UTL_FILE.NEW_LINE(l_output); --这种方式记事本打开文件不换行  
      --EXECUTE THE QUERY STATEMENT  
      L_STATUS := DBMS_SQL.EXECUTE(l_theCursor);  --EXECUTE:执行指定的游标 

      --DUMP TABLE COLUMN VALUE  
      WHILE (DBMS_SQL.FETCH_ROWS(l_theCursor) > 0) LOOP   -- FETCH_ROWS:从指定的游标中取出记录 
        l_separator :=  '';
        FOR I IN 1 .. l_colCnt LOOP  
          DBMS_SQL.COLUMN_VALUE(l_theCursor, I, l_columnValue);   --COLUMN_VALUE:返回游标中指定位置的元素
          UTL_FILE.PUT(l_output,l_separator || l_columnValue );
          l_separator := ',';  
        END LOOP; 
        UTL_FILE.put(l_output,chr(13)||chr(10));
        UTL_FILE.NEW_LINE(l_output,0); 
        --UTL_FILE.NEW_LINE(l_output);  
      END LOOP;  
      --下面这部分为另外一种写法,也可行
--    for i in 1 .. 255 loop  
--        begin  
--            dbms_sql.define_column( l_theCursor, i,l_columnValue, 2000 );  --DEFINE_COLOUMN:定义字段变量,其值对应于指定游标中某个位置元素的值
--            l_colCnt := i;  
--        exception  
--            when others then  
--                if ( sqlcode = -1007 ) then exit;  
--                else  
--                    raise;  
--                end if;  
--        end;  
--    end loop;  
--    DBMS_OUTPUT.PUT_LINE('l_colCnt: '||l_colCnt);  
--    dbms_sql.define_column( l_theCursor, 1, l_columnValue,2000 );  
--  
--    l_status := dbms_sql.execute(l_theCursor);  --EXECUTE:执行指定的游标 
--  --EmpID,    First,  PreferredName,  Middle, Last,   Gender, DateOfBirth ,OrigHireDate,  LastHireDate,   JobCode,    JobTitle,
--  --SupervisorID  ,SupvName   ,EmailAddress   ,WrkPhoneNo,    WrkLoc, TermDate    ,Business Group,    ITAR Compliant  ,MobilePhoneNo  ,
--  --FuncReportsTo ,Department ,AltTitle,  MorE,   Mailstop,   Company,    FullorPartTime, AD Acct_NTUserID
--
--    utl_file.put( l_output, 'Empid,First,PreferredName,Middle,last,Gender,DateOfBirth,OrigHireDate,LastHireDate,JobCode,JobTitle,SupervisorID,SupvName,EmailAddress,WrkPhoneNo,WrkLoc,TermDate,Business Group,ITAR Compliant,MobilePhoneNo,FuncReportsTo,Department,AltTitle,MorE,Mailstop,Company,FullorPartTime,AD Acct_NTUserID,BANKNAME,BANKBRANCHNAME, BANKACCNAME, BANKACCNUMBER, BANKACCCURRENCY');  
--    utl_file.new_line( l_output );  
----    utl_file.put_line( l_output, 'EmpID,First,PreferredName,Middle,Last,Gender,DateOfBirth,OrigHireDate,LastHireDate,JobCode,JobTitle,SupervisorID,SupvName,EmailAddress,WrkPhoneNo,WrkLoc,TermDate,Business Group,ITAR Compliant,MobilePhoneNo,FuncReportsTo,Department,AltTitle,MorE,Mailstop,Company,FullorPartTime,AD Acct_NTUserID');  
--
--    loop  
--        exit when ( dbms_sql.fetch_rows(l_theCursor) <= 0 );  -- FETCH_ROWS:从指定的游标中取出记录 
--        l_separator := '';  
--        for i in 1 .. l_colCnt loop  
--            dbms_sql.column_value( l_theCursor, i,l_columnValue );                  
--            utl_file.put( l_output, l_separator ||l_columnValue);  --COLUMN_VALUE:返回游标中指定位置的元素
--            l_separator := ',';  
--        end loop;  
--        utl_file.put(l_output, '  ');
--        utl_file.new_line( l_output );  
--        l_cnt := l_cnt+1;  
--    end loop;  
    dbms_sql.close_cursor(l_theCursor);  --CLOSE_CURSOR:关闭指定的游标并释放内存 

    utl_file.fclose( l_output );  --CLOSE FILE  
    EXCEPTION  
      WHEN OTHERS THEN 
        SEND_LOG('Error when output file :'||SQLCODE||'-'||SQLERRM);
        RAISE;  
    END;  
    -------获取ftp服务器信息,这里我开始在前台有定义一个表结构和表值来保存服务器信息
    BEGIN
      FOR cur_temp IN cur_ftp_info(ic_table_name,ic_row_name)
      LOOP
        IF cur_temp.column_name   ='FTP_SERVER_PASSWORD' THEN
         vc_ftp_password        :=cur_temp.p_value;
        ELSIF cur_temp.column_name='FTP_SERVER_PORT' THEN
         vc_ftp_server_port     :=cur_temp.p_value;
       ELSIF cur_temp.column_name='FTP_SERVER_ACCOUNT' THEN
         vc_ftp_account         :=cur_temp.p_value;
        ELSIF cur_temp.column_name='FTP_SERVER_HOST' THEN
         vc_ftp_server_host     :=cur_temp.p_value;
       END IF;
      END LOOP;

      IF vc_ftp_password IS NULL OR vc_ftp_server_port IS NULL OR vc_ftp_account IS NULL OR vc_ftp_server_host IS NULL THEN
        SEND_OUTPUT('Can not get ftp server information: please check the value of table name,row name,form');
        RAISE_APPLICATION_ERROR(-20001,'Error when get ftp server information:'||SQLCODE||'-'||SQLERRM);
      END IF;
    --ML_FTP 就是网上的ftp
      l_conn := ML_FTP.login(vc_ftp_server_host,vc_ftp_server_port,vc_ftp_account,vc_ftp_password);  
      ML_FTP.binary(p_conn => l_conn);   --  Binary模式不会对数据进行任何处理 
      ML_FTP.put(p_conn      => l_conn, 
              p_from_dir  => 'UTL_FILE_DIR',  --这里的路径名注意要用大写
              p_from_file => p_filename,   --服务器上的文件名
              p_to_file   => IC_FILE_NAME ); --想要在服务器上生成的文件名称
      ML_FTP.logout(l_conn);  
      utl_tcp.close_all_connections; 
      SEND_OUTPUT('upload file to ftp completed.');
    EXCEPTION
    WHEN OTHERS THEN
      SEND_LOG('Error when upload file to ftp:'||SQLCODE||'-'||SQLERRM);
      RAISE_APPLICATION_ERROR(-20001,'Error when upload file to ftp:'||SQLCODE||'-'||SQLERRM);
    END;
  END ML_OPCM_INFORMATION;
END ML_OPCM_INFORMATION_UPLOAD;

定期上传就在ebs前台设置一个job即可
或者后台设置
ORACLE JOB有定期执行的功能,具体的可以看这个文档
ORACLE JOB定时任务 https://wenku.baidu.com/view/7cc4cf47866fb84ae55c8d04.html
–查询后台JOB
SELECT * FROM DBA_JOBS;
字段含义

猜你喜欢

转载自blog.csdn.net/qq_37613533/article/details/81509093
今日推荐