You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Oracle PL/SQL读取FTP或SFTP服务器上的.csv文件

如何用Oracle SQL/PLSQL读取FTP/SFTP上的CSV文件?

兄弟,你用UTL_TCP拿到那个SSH-2.0-OpenSSH_5.3的返回确实说明连接通了,但说实话,用UTL_TCP来搞FTP/SFTP实在太折腾了——这玩意儿是底层TCP工具,你得自己手动实现FTP的USER/PASS命令、SFTP的SSH握手这些协议细节,根本没必要!我给你捋捋更简单的方案:

一、处理普通FTP服务器的CSV文件

如果是普通FTP(非SFTP),直接用Oracle自带的UTL_FTP包就行,比UTL_TCP友好太多,不用自己拼协议命令。步骤大概是这样:

  • 建立FTP连接
  • 登录服务器
  • 切换到文件所在目录
  • 逐行读取或者下载文件到数据库目录
  • 处理CSV内容(比如拆分字段插入表)
  • 关闭连接

给你个实际可用的示例代码:

DECLARE
  l_conn UTL_FTP.connection;
  l_line VARCHAR2(4000);
BEGIN
  -- 建立FTP连接,替换成你的服务器地址和端口
  l_conn := UTL_FTP.open_connection('ftp.******.******.com', 21);
  -- 登录,替换成你的FTP用户名和密码
  UTL_FTP.login(l_conn, 'your_ftp_username', 'your_ftp_password');
  -- 切换到CSV文件所在的远程目录
  UTL_FTP.cd(l_conn, '/path/to/your/csv/folder');
  
  -- 切换到ASCII模式(适合文本类的CSV文件)
  UTL_FTP.ascii(l_conn);
  -- 逐行读取CSV文件(替换成你的文件名)
  LOOP
    BEGIN
      UTL_FTP.get_line(l_conn, l_line);
      -- 这里可以添加逻辑处理每一行,比如拆分CSV字段插入到表中
      DBMS_OUTPUT.PUT_LINE('读取到行:' || l_line);
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        -- 没有更多行时退出循环
        EXIT;
    END;
  END LOOP;
  
  -- 关闭连接
  UTL_FTP.close_connection(l_conn);
EXCEPTION
  WHEN OTHERS THEN
    -- 异常时确保连接关闭
    IF UTL_FTP.is_open(l_conn) THEN
      UTL_FTP.close_connection(l_conn);
    END IF;
    RAISE;
END;
/

二、处理SFTP服务器的CSV文件

如果是SFTP(基于SSH的安全FTP),UTL_FTP就不管用了,因为SFTP走的是SSH协议,Oracle没有内置的SFTP包,给你两个实用方案:

方案1:用Java存储过程调用JSch库

Java有成熟的SSH/SFTP客户端库JSch,我们可以把它导入数据库,写个Java存储过程来处理SFTP下载,再用PLSQL调用:

第一步:创建Java源(需要先把JSch的jar包导入数据库)

CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "SFTPReader" AS
import com.jcraft.jsch.*;
import java.io.*;

public class SFTPReader {
  public static void downloadSFTPFile(String host, int port, String user, String pass, String remoteFilePath, String localFilePath) throws Exception {
    JSch jsch = new JSch();
    // 建立SSH会话
    Session session = jsch.getSession(user, host, port);
    session.setPassword(pass);
    // 关闭主机密钥检查(生产环境建议配置可信密钥)
    session.setConfig("StrictHostKeyChecking", "no");
    session.connect();
    
    // 打开SFTP通道
    Channel channel = session.openChannel("sftp");
    channel.connect();
    ChannelSftp sftpChannel = (ChannelSftp) channel;
    
    // 下载远程文件到本地目录
    OutputStream os = new FileOutputStream(localFilePath);
    sftpChannel.get(remoteFilePath, os);
    
    // 关闭资源
    os.close();
    sftpChannel.exit();
    session.disconnect();
  }
}
/

第二步:创建PLSQL包装器

CREATE OR REPLACE PROCEDURE SFTP_DOWNLOAD_FILE(
  p_host VARCHAR2,
  p_port NUMBER,
  p_user VARCHAR2,
  p_pass VARCHAR2,
  p_remote_file VARCHAR2,
  p_local_file VARCHAR2
) AS
LANGUAGE JAVA NAME 'SFTPReader.downloadSFTPFile(java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String)';
/

第三步:调用存储过程下载,再用外部表读取

BEGIN
  -- 替换成你的SFTP信息和文件路径
  SFTP_DOWNLOAD_FILE(
    'ftp.******.******.com',
    22, -- SFTP默认端口是22,如果你连的是21端口,这里改成21
    'your_sftp_username',
    'your_sftp_password',
    '/path/to/your/data.csv',
    '/u01/oracle/local_data/data.csv' -- 数据库服务器上的本地目录,需要配置成Oracle的DIRECTORY对象
  );
END;
/

然后创建外部表读取本地的CSV文件:

-- 先创建目录对象(需要DBA权限)
CREATE OR REPLACE DIRECTORY DATA_DIR AS '/u01/oracle/local_data';
GRANT READ, WRITE ON DIRECTORY DATA_DIR TO your_user;

-- 创建外部表,字段对应你的CSV结构
CREATE TABLE csv_external_table (
  column1 VARCHAR2(100),
  column2 NUMBER,
  column3 DATE,
  column4 VARCHAR2(200)
)
ORGANIZATION EXTERNAL (
  TYPE ORACLE_LOADER
  DEFAULT DIRECTORY DATA_DIR
  ACCESS PARAMETERS (
    RECORDS DELIMITED BY NEWLINE
    FIELDS TERMINATED BY ','
    OPTIONALLY ENCLOSED BY '"'
    MISSING FIELD VALUES ARE NULL
    -- 如果有表头,可以加这句跳过第一行:SKIP 1
  )
  LOCATION ('data.csv')
)
REJECT LIMIT UNLIMITED;

方案2:用OS工具结合外部表

如果数据库服务器能直接访问SFTP服务器,也可以写个shell脚本用sftp命令把文件下载到本地目录,然后用外部表读取——这种方式不用搞Java存储过程,适合批量处理场景。

三、关于你之前的UTL_TCP尝试

你连接21端口得到SSH的返回信息,这说明你连接的服务器其实是SFTP服务(可能对方把SFTP端口改成21了),因为普通FTP的返回应该是类似220 FTP Server ready的内容,而SSH的返回是SSH-2.0-OpenSSH_5.3,所以别再用UTL_TCP硬怼了,用上面的SFTP方案更靠谱。

内容的提问来源于stack exchange,提问作者Vijay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:20:34