`
wuhuizhong
  • 浏览: 682672 次
  • 性别: Icon_minigender_1
  • 来自: 中山
社区版块
存档分类
最新评论

FTP From PL/SQL

 
阅读更多

Sometimes it's preferable to trigger FTP jobs directly from PL/SQL rather than rely on CRON or AT. This article contains a brief description of the two methods I use.

Shell Script

The first method relies on a java stored procedure, described in Shell Commands From PL/SQL, which can be used to trigger a shell script to perform the transfer. The shell script may look like the following.

#! /bin/ksh

# Move to appropriate directory on local server
cd /extracts

# FTP all files in directory
ftp -inv ftp.company.com <<EOF
user ftpuser ftppassword
# Move to appropriate directory on remote server.
cd /loads
ascii
mput *.*
bye
EOF

PL/SQL FTP API

The second approach uses a combination of the UTL_TCP and UTL_FILE packages to create a simple FTP API (ftp.pksftp.pkb). Once the API is loaded into the appropriate schema simple FTP commands can be initiated as follows.

CREATE OR REPLACE DIRECTORY my_docs AS '/u01/app/oracle/';
SET SERVEROUTPUT ON SIZE 1000000
@c:\ftp.pks
@c:\ftp.pkb

-- Retrieve an ASCII file from a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.ascii(p_conn => l_conn);
  ftp.get(p_conn      => l_conn,
          p_from_file => '/u01/app/oracle/test.txt',
          p_to_dir    => 'MY_DOCS',
          p_to_file   => 'test_get.txt');
  ftp.logout(l_conn);
END;
/

-- Send an ASCII file to a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.ascii(p_conn => l_conn);
  ftp.put(p_conn      => l_conn,
          p_from_dir  => 'MY_DOCS',
          p_from_file => 'test_get.txt',
          p_to_file   => '/u01/app/oracle/test_put.txt');
  ftp.logout(l_conn);
END;
/

-- Retrieve a binary file from a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.binary(p_conn => l_conn);
  ftp.get(p_conn      => l_conn,
          p_from_file => '/u01/app/oracle/product/9.2.0.1.0/sysman/reporting/gif/jobs.gif',
          p_to_dir    => 'MY_DOCS',
          p_to_file   => 'jobs_get.gif');
  ftp.logout(l_conn);
END;
/

-- Send a binary file to a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.binary(p_conn => l_conn);
  ftp.put(p_conn      => l_conn,
          p_from_dir  => 'MY_DOCS',
          p_from_file => 'jobs_get.gif',
          p_to_file   => '/u01/app/oracle/jobs_put.gif');
  ftp.logout(l_conn);
END;
/

-- Get a directory listing from a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
  l_list  ftp.t_string_table;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.list(p_conn   => l_conn,
           p_dir   => '/u01/app/oracle',
           p_list  => l_list);
  ftp.logout(l_conn);
  
  IF l_list.COUNT > 0 THEN
    FOR i IN l_list.first .. l_list.last LOOP
      DBMS_OUTPUT.put_line(i || ': ' || l_list(i));
    END LOOP;
  END IF;
END;
/

-- Get a directory listing (file names only) from a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
  l_list  ftp.t_string_table;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.nlst(p_conn   => l_conn,
           p_dir   => '/u01/app/oracle',
           p_list  => l_list);
  ftp.logout(l_conn);
  
  IF l_list.COUNT > 0 THEN
    FOR i IN l_list.first .. l_list.last LOOP
      DBMS_OUTPUT.put_line(i || ': ' || l_list(i));
    END LOOP;
  END IF;
END;
/

-- Rename a file on a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.rename(p_conn => l_conn,
             p_from => '/u01/app/oracle/dba/shutdown',
             p_to   => '/u01/app/oracle/dba/shutdown.old');
  ftp.logout(l_conn);
END;
/

-- Delete a file on a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.delete(p_conn => l_conn,
             p_file => '/u01/app/oracle/dba/temp.txt');
  ftp.logout(l_conn);
END;
/

-- Create a directory on a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.mkdir(p_conn => l_conn,
            p_dir => '/u01/app/oracle/test');
  ftp.logout(l_conn);
END;
/

-- Remove a directory from a remote FTP server.
DECLARE
  l_conn  UTL_TCP.connection;
BEGIN
  l_conn := ftp.login('ftp.company.com', '21', 'ftpuser', 'ftppassword');
  ftp.rmdir(p_conn => l_conn,
            p_dir  => '/u01/app/oracle/test');
  ftp.logout(l_conn);
END;
/

The basic functions are implemented using LOBs to allow FTP without having to access files on the local filesystem. The get and put procedures string these together to form a complete job using all the functions. If a straight forward FTP to, or from, the local filesystem is required it is more efficient to use theGET_DIRECT and PUT_DIRECT procedures as they avoid the temporary LOBs.

The current implementation has the following issues:

  • The mput and mget operations are not supported directly, but can be implemented using a combination of the list/nlst and get/put operations.
  • The implementation of binary transfers relies on UTL_FILE features only available in Oracle9i Release 2 upwards.
  • There is no support for ASCII mode in the PUT_DIRECT procedure.

Thanks to Hans van Doormalen for noticing I wasn't closing my passive connections. I do now :)

ACL for 11g

The introduction of Fine-Grained Access to Network Services in Oracle Database 11g Release 1 means you will need to configure an access control list (ACL) to allow UTL_TCP to access the network. The examples above work correctly with the following basic ACL. You will need to amend the FTP server details and username details to match your FTP server address and the Oracle username running the FTP API.

DECLARE
  l_acl_name         VARCHAR2(30) := 'utl_tcp.xml';
  l_ftp_server_ip    VARCHAR2(20) := '192.168.0.131';
  l_ftp_server_name  VARCHAR2(20) := 'ftp.company.com';
  l_username         VARCHAR2(30) := 'TEST';
BEGIN
  DBMS_NETWORK_ACL_ADMIN.create_acl (
    acl          => l_acl_name, 
    description  => 'Allow connections using UTL_TCP',
    principal    => l_username,
    is_grant     => TRUE, 
    privilege    => 'connect',
    start_date   => SYSTIMESTAMP,
    end_date     => NULL);

  COMMIT;

  DBMS_NETWORK_ACL_ADMIN.add_privilege ( 
    acl         => l_acl_name, 
    principal   => l_username,
    is_grant    => FALSE, 
    privilege   => 'connect', 
    position    => NULL, 
    start_date  => NULL,
    end_date    => NULL);

  COMMIT;

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => l_acl_name,
    host        => l_ftp_server_ip, 
    lower_port  => NULL,
    upper_port  => NULL);

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => l_acl_name,
    host        => l_ftp_server_name, 
    lower_port  => NULL,
    upper_port  => NULL);

  COMMIT;
END;
/

 

http://www.oracle-base.com/articles/misc/ftp-from-plsql.php

分享到:
评论

相关推荐

    Oracle P/L SQL实现FTP上传、下载功能

    Oracle P/L SQL实现FTP上传、下载功能,以下是此过程包的头部,包体经常打包处理plb,感兴趣用户可以下载下来。 --Oracle上的FTP功能 Create or Replace Package UTL_FTP AUTHID CURRENT_USER as Type Connection ...

    ORACLE中的FTP例子代码

    2. `ORACLE-BASE - FTP From PL-SQL in Oracle in Oracle.files`:这个名字看起来像是一个文件夹或者包含多个文件,可能提供了额外的代码示例或相关资源。 为了实际应用这些知识,你需要查看HTML文件中的具体代码...

    定时导出Oracle数据库数据并上传到FTP目录脚本

    Oracle提供了多种数据导出工具,如SQL*Plus的`spool`命令、`expdp`(数据泵导出)或PL/SQL程序。在这个案例中,由于我们希望导出特定表的特定字段,可能需要结合SQL查询来实现。例如,你可以编写一个SQL查询,使用`...

    Linux FTP服务搭建

     connetc_from_port_20=YES|NO  ftp_data_port=port number  port_promiscuous=YES|NO 关于被动模式的相关配置参数如下:  pasv_enable=YES|NO  pasv_min_port=port number  pasv_promiscuous=YES|NO ...

    解决8080端口冲突

    具体来说,我们可以使用 system 用户登录 PL/SQL,然后执行以下SQL语句: ``` SQL&gt; call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),'/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()','...

    oracle 10g 单实例 升级方案文档.docx

    - PL/SQL Release: `10.2.0.1.0 - Production` - CORE: `10.2.0.1.0 Production` - TNS for 32-bit Windows: `Version 10.2.0.1.0 - Production` - NLS RTL Version: `10.2.0.1.0 - Production` ##### 2.4 停止...

    LINUX-下ORACLE利用rman备份迁移数据库.docx

    SQL查询`select count(*) from v$datafile`检查数据文件的数量,然后通过PL/SQL块动态生成新的数据文件名称,以便在恢复时使用。 3. **备份的传输**: 利用FTP工具,如所示,将RMAN备份文件从源服务器传输到目标...

    Oracle-不同数据库DBLINK导数据使用说明

    1. **使用PL/SQL包**:Oracle提供了多个内置包,如DBMS_LOB,用于高效地处理LOB数据。通过调用这些包的方法,可以在两个数据库之间安全地传输BLOB数据。 2. **分块传输**:对于特别大的BLOB数据,可以考虑将其分割...

    最完整的Toad For Oracle使用手册

    - **Audit SQL/Sys Privs**:介绍了审计SQL和系统权限的方法。 - **NLS Parameters**:提供了NLS参数的管理方法。 - **Toad Features Security**:讲述了Toad特性安全性的管理。 - **ASM Manager**:介绍了ASM管理器...

    bugzilla安装步骤

    Allow from all &lt;/Directory&gt; ``` - 修改`DocumentRoot`为Bugzilla目录: ```apacheconf DocumentRoot "/var/www/html/bugzilla" ``` - 重启Apache服务: ```bash [root@mail/]# service httpd restart `...

Global site tag (gtag.js) - Google Analytics