1. 需求
在服务器2(数据库服务器)操控服务器1(数据库服务器)上的一个含有blob字段的表格,导出该blob字段到服务器1的一个文件。
2. 方案
2.1 展示图
为了传输文件的目的,有一个DBMS_FILE_TRANSFER包,它含有put_file过程用于在远端文件系统创建一份拷贝。但是,它要求被复制的文件的大小必须是512字节的整数倍,我们很难保证每个文件都能达到这个要求。换句话说,当我们利用该过程来传输任意大小的文件时,我们会得到违背该条要求的错误信息。
2.2 步骤
2.2.1 在服务器1上
-
在服务器1上创建一个含有blob字段的表格.
blob_export(
id number,
photoblob)
-
向该表格插入一些数据.
-
在服务器1上建立一个目录,比如 '/tmp/photo_export'
2.2.2 在服务器2上
-
在服务器2上建立一个指向服务器1的dblink.
-
在服务器2上建立一个material view.
建立material view的原因是我们不能直接使用远程表格的LOB指针(Error ORA-22992).
-
在服务器2上建立一个db directory,比如 'LOCAL_PHOTO_EXPORT' 指向 '/tmp/photo_export'
CREATE OR REPLACE DIRECTORY LOCAL_PHOTO_EXPORT AS '/tmp/photo_export';
GRANT all ON DIRECTORY LOCAL_PHOTO_EXPORT TO user;
- 在服务器2上创建一个shell脚本用于sftp.
-
#!/bin/expect
set timeout -1
puts $argc
if { $argc<6 } {
puts "Usage $argv0 host user passwd localdir filename remotedir"
exit 1
}
set host [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
set localdir [lindex $argv 3]
set filename [lindex $argv 4]
set remotedir [lindex $argv 5]
puts $host
puts $user
puts $passwd
puts $localdir
puts $filename
puts $remotedir
spawn /usr/bin/sftp -oStrictHostkeyChecking=no -oCheckHostIP=no $user@$host
expect *assword:
send "$passwd\r"
expect sftp>
send "cd $remotedir\r"
expect sftp>
send "lcd $localdir\r"
expect sftp>
send "put $filename\r"
expect sftp>
send "exit\r"
expect eof
-
在服务器2上创建一个java source用于执行系统命令.
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Host" AS
import java.io.*;
public class Host {
public static void executeCommand(String command) {
try {
String[] finalCommand;
if (isWindows()) {
finalCommand = new String[4];
finalCommand[0] = "C:\\windows\\system32\\cmd.exe";
finalCommand[1] = "/y";
finalCommand[2] = "/c";
finalCommand[3] = command;
}
else {
finalCommand = new String[3];
finalCommand[0] = "/bin/sh";
finalCommand[1] = "-c";
finalCommand[2] = command;
}
System.out.println(command);
final Process pr = Runtime.getRuntime().exec(finalCommand);
new Thread(new Runnable() {
public void run() {
try {
BufferedReader br_in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String buff = null;
while ((buff = br_in.readLine()) != null) {
System.out.println("Process out :" + buff);
try {Thread.sleep(100); } catch(Exception e) {}
}
br_in.close();
}
catch (IOException ioe) {
System.out.println("Exception caught printing process output.");
ioe.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
BufferedReader br_err = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String buff = null;
while ((buff = br_err.readLine()) != null) {
System.out.println("Process err :" + buff);
try {Thread.sleep(100); } catch(Exception e) {}
}
br_err.close();
}
catch (IOException ioe) {
System.out.println("Exception caught printing process error.");
ioe.printStackTrace();
}
}
}).start();
}
catch (Exception ex) {
System.out.println(ex.getLocalizedMessage());
}
}
public static boolean isWindows() {
if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1)
return true;
else
return false;
}
};
/
-
创建一个package用于包含实现需求的存储过程。
create or replace PACKAGE FILE_TRANSFER AS
PROCEDURE REMOTE_BLOB_EXPOERT (P_LOCAL_DIRECTORY in varchar2);
PROCEDURE SFTP(P_HOST in varchar2,P_USER in varchar2,P_PASSWD in varchar2,P_REMOTE_DIR in varchar2, P_LOCAL_DIR in varchar2, P_FILE_NAME in varchar2);
PROCEDURE EXPORT_SFTP;
PROCEDURE host_command (p_command IN VARCHAR2);
END FILE_TRANSFER;
-
其中, host_command过程定义如下:
PROCEDURE host_command (p_command IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'Host.executeCommand (java.lang.String)';
它实际是调用刚建立的java source来执行系统命令。REMOTE_BLOB_EXPOERT 用于导出blob到文件,SFTP用于从服务器2传输文件到服务器1,EXPORT_SFTP是执行所有功能的入口。
CREATE OR REPLACE PACKAGE BODY "CDU_IDM"."FILE_TRANSFER" AS
/*
purpose:export a remote blob column to a local directory
before running this:
1. a db link established;
2. a material view is established;
3. a local directory is established;
*/
PROCEDURE REMOTE_BLOB_EXPOERT(P_LOCAL_DIRECTORY in varchar2) AS
l_id number;
l_photo_len number;
l_photo blob;
l_file UTL_FILE.FILE_TYPE;
l_buffer RAW(32767);
l_amount BINARY_INTEGER := 32767;
l_pos NUMBER := 1;
c_photo_ext varchar2(5);
l_file_name varchar2(30);
BEGIN
c_photo_ext :='.png';
--mv_blob_export is the material view getting a blob column via a db link
for rec in
(select *
from mv_blob_export)
loop
l_id:=rec.id;
l_photo:=rec.photo;
l_photo_len := DBMS_LOB.getlength(l_photo);
l_file_name := to_char(l_id)||c_photo_ext;
--open file
l_file := UTL_FILE.fopen(P_LOCAL_DIRECTORY,l_file_name,'wb',32767);
--write file
WHILE l_pos < l_photo_len LOOP
DBMS_LOB.read(l_photo, l_amount, l_pos, l_buffer);
UTL_FILE.put_raw(l_file, l_buffer, TRUE);
l_pos := l_pos + l_amount;
END LOOP;
-- Close the file.
UTL_FILE.fclose(l_file);
end loop;
END REMOTE_BLOB_EXPOERT;
PROCEDURE host_command (p_command IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'Host.executeCommand (java.lang.String)';
/*
purpose: transfer a file by sftp
before running this:
1. a sftp shell script is established
*/
PROCEDURE SFTP(P_HOST in varchar2,P_USER in varchar2,P_PASSWD in varchar2,P_REMOTE_DIR in varchar2, P_LOCAL_DIR in varchar2, P_FILE_NAME in varchar2) AS
l_sftp_prog VARCHAR2(100) := '/tmp/photo_export/sftp.sh';
l_sftp_command VARCHAR2(500);
BEGIN
l_sftp_command := l_sftp_prog || ' "' || p_host || '" "' || p_user || '" "' ||
p_passwd || '" "'|| p_local_dir || '" "' ||
p_file_name||'" "'|| p_remote_dir||'"' ;
dbms_output.put_line(l_sftp_command);
host_command(l_sftp_command);
END SFTP;
/*
a combine procedure for usage
*/
PROCEDURE EXPORT_SFTP AS
l_LOCAL_DIRECTORY varchar2(30) :='LOCAL_PHOTO_EXPORT';
l_host VARCHAR2(100) := 'server1.xxx.com';
l_user VARCHAR2(100) := 'sftpuser';
l_passwd VARCHAR2(100) := 'password';
l_remote_dir VARCHAR(500) := '/tmp/photo_export';
l_local_dir VARCHAR2(500) := '/tmp/photo_export';
c_photo_ext varchar2(5):='.png';
l_file_name varchar2(100):='*'||c_photo_ext;
BEGIN
REMOTE_BLOB_EXPOERT(l_LOCAL_DIRECTORY);
sftp(l_host,l_user,l_passwd,l_remote_dir,l_local_dir,l_file_name);
END EXPORT_SFTP;
END FILE_TRANSFER;
/
-
最后,执行EXPORT_SFTP过程来实现整个功能.
set serveroutput on;
call dbms_java.set_output(50);
begin
file_transfer.export_sftp;
end;
参考
- Extract files from an Oracle BLOB fieldhttp://stackoverflow.com/questions/6332032/how-can-i-extract-files-from-an-oracle-blob-field
- SFTP from PLSQL https://slobaray.com/2015/09/10/sftp-from-plsql/
- What is SFTP, and how do I use it to transfer fileshttps://kb.iu.edu/d/akqg
- Install Tclhttp://www.linuxfromscratch.org/blfs/view/svn/general/tcl.html
- Install Expecthttp://www.linuxfromscratch.org/blfs/view/svn/general/expect.html
分享到:
相关推荐
批量导出Oracle数据库中的BLOB字段生成图片,是一项常见的需求,尤其对于那些需要将数据库中的图片资源导出到本地文件系统的情况。下面将详细介绍这一过程及其相关知识点。 首先,我们需要理解BLOB类型。BLOB...
总的来说,"Oracle导出Clob,Blob工具版本2" 是一个针对Oracle数据库CLOB和BLOB数据的高效解决方案,旨在提供更快速、更可靠的导出服务。对于那些需要频繁处理大对象数据的开发人员和DBA来说,这是一个非常有价值的...
本教程将详细讲解如何批量导出Oracle数据库中的BLOB字段并生成文件,适用于需要定期或一次性处理大量图片或其他BLOB数据的场景。 首先,确保你已经在本地安装了Oracle客户端。Oracle客户端提供了SQL*Plus和其他工具...
2. **Oracle.ManagedDataAccess.dll**:这是Oracle官方提供的Managed Driver,它是一个.NET Framework库,允许开发者在.NET环境中直接访问Oracle数据库,支持Clob和Blob操作。 3. **SqlSugar.dll**:这是一个流行的...
批量导出oracle bolb图片到本地文件
使用PL/SQL脚本将Oracle的Blob字段中存储的图片批量导出到文件夹,可在文件夹中直接查看。
oracle expdp导出blob字段遇到ora-01555报错的解决方案
总结来说,从Oracle的BLOB类型字段中提取并转换到MySQL的过程涉及到查询、导出、上传等多个步骤。在实际操作中,需要对数据库API有深入理解,并注意数据的兼容性和性能优化。通过以上方法,你可以顺利地在两个数据库...
这款工具设计的目的是为了帮助用户方便地从Oracle数据库中批量提取并导出Blob字段中的图片至指定的文件夹。 首先,用户需要在运行这个exe可执行文件前确保已安装了Oracle 10g客户端。Oracle 10g客户端是与Oracle...
Oracle照片导出是一款基于C#开发的工具,主要用于从Oracle数据库中导出Blob类型的图片数据。Blob(Binary Large Object)是Oracle数据库用于存储大对象,如图像、音频或视频文件等非结构化数据的数据类型。这个工具...
2. **数据导出**:使用ORACLE提供的工具,如SQL*Plus或者PL/SQL Developer,或者通过编写SQL查询或存储过程来提取BLOB数据。通常,我们可以将BLOB数据转化为HEX字符串或Base64编码,以便在文本格式下传输。 3. **...
批量导出Blob工具是一种专门针对这类数据进行批量处理的实用程序,旨在提高数据库管理和数据迁移的效率。本工具的核心功能在于,它允许用户通过修改配置文件来适应不同的数据库环境,并且支持自定义数据导出的需求。...
在Oracle数据库中,Blob是一种用来存储二进制数据的数据类型,比如图像、音频或视频文件等。本篇文章将详细介绍如何通过SQL查询语句获取存储在Blob字段中的JPEG格式照片的像素大小。 ### 1. 了解Blob数据类型 在...
Python如何操作Oracle的Blob字段,
在IT领域,尤其是在Java开发与Oracle数据库交互的过程中,处理BLOB(Binary Large Object)类型字段是一项常见且重要的任务。BLOB字段主要用于存储大量的二进制数据,如图像、音频、视频或任何其他非文本格式的数据...
在数据库管理中,有时我们需要将数据从一个环境迁移到另一个环境,或者备份某些表的数据,这时“Oracle导出INSERT语句”的工具就显得非常实用。 这个小工具的核心功能是将Oracle数据库中的数据转换为一系列的INSERT...
`UTL_RAW.CAST_TO_VARCHAR2`是Oracle提供的一个包中的函数,用于将RAW或BLOB类型的二进制数据转换为VARCHAR2字符串类型。这一步骤对于将BLOB转换为CLOB至关重要,因为CLOB本质上是一种字符数据类型,而不能直接与二...
知识点2:ORACLE数据库BLOB字段 * BLOB(Binary Large OBject)是一种数据库字段类型,用于存储二进制数据,如图片、音频、视频等。 * ORACLE数据库的BLOB字段可以存储大量的二进制数据,且性能优于LONG字段。 ...
### Oracle Blob类型转换为文件读取的相关知识点 在软件开发过程中,尤其是在处理数据库中的二进制大对象(Binary Large Object, 简称BLOB)时,经常需要将数据库中的BLOB数据转换为文件进行读取或处理。本文将详细...
在Oracle数据库上导出上千万上亿数据的工具 cmd 到本目录 然后执行如下命令: ->sqluldr2.exe user=用户名/密码@数据库 query="查询语句" table=表名 head=yes FILE=存放路径 例如:sqluldr2.exe user=u/pass@db ...