通过SQLDEVELOPER图形对ORACLE中的BLOB文件直接导出

0、问题由来

昨天群里小伙伴半夜发布问题,怎么把blob从库里导到本地,文件很多。网上有很多说法,大多是导出照片、PDF、这种同一类型的文件,办法基本都是通过创建存储过程,把文件直接导出到数据库服务器本地磁盘上。
在查阅了官方文档和bing之后,找出如下两个方法,直接用图形化工具导出,并且实验验证了确实可行。感谢运维大佬“北方的猫”鼎力相助解决脚本适配问题

1、准备下环境

下面简单记录一下实现过程。

首先这个是有个前提条件,包含blob的表里得有1个列是写的真实文件名带扩展后缀,要不然导出的文件没法知道是什么类型的文件。比如说你这个列里即有pdf也有word还有jpg或者压缩包啥的有。

实验基础环境准备如下:

1、准备sqldeveloper软件,下最新版本就行,别搞低版本过来。

2、解锁scott用户,创建一张数据表table_log_test(别问我为啥叫这不搭边的名,测试时随便写的

图片

),这张表的数据结构如下表所示:

ID

VARCHAR2(20 BYTE)

CONTENT

BLOB

FILE_NAME

VARCHAR2(200 BYTE)

创建完之后,往里面创建两条数据,扔2个Excel文件

图片

3、数据创建成功后,对数据表进行导出,可以选左侧树中找到数据表,右键--导出(根据实际情况,这里你也可以写sql筛选一下,在结果哪里也可以右键导出。)

图片

参照下图配置:

取消“导出DDL”

勾选“导出数据”

格式修改为“loader"

另存为修改为”单独目录“

文件修改为”你要导出存储BLOB的目录“,这里我选择D:\lob。

然后点击下一步

图片

继续下一步

图片

点完成导出文件到本地

图片

导出后显示如下目录内容如下

图片

其中”表名xxxx-xxx-xxx.ldr“命名的就是blob文件

其中”表名.ldr"命名的文件就是记录数据表列内容的文件,

图片

其中”表名.ctl"命名的文件就是控制文件,总的来就是sqlloader那一套东西给图形化了,省了不少事。

图片

至此,基本测试环境准备完毕。下面要说的就是两种把blob导出的原始文件变成真实可用的文件。

2、方法1

--方法1,官方文档的方法

说白了就是使用python脚本进行对原始文件重命名,哈哈哈。

唯一坑的地方就是官方文档里贴出来的python脚本没有格式化,完全没法用,我擦。我和大佬研究了半天才用上。

而且官方文档还给了这么一句,大致就是python脚本只用来Demo的。不是产品,不受支持

还给了你另一个选择,就是一会要说的方法2要说到的用SQLCL+JS脚本来执行。

图片

话接回方法1,虽说是Demo,好歹给格式化一下文件啊,给的脚本长这样。。。。。。。,没有缩进空格的脚本粘贴出来根本无法执行啊。

图片

后来大佬给重新加工了一下脚本,改完之后长这样(使用这个得严格按照说明的3列来进行导出,调换顺序名就串了。。。。):

#该脚本是针对3列,序号|原始文件名|真实文件名,顺序不能错
import os

zip_location = input("输入目录:")
hdr_file_name = input("输入文件名: ")

f = open(zip_location+"\\"+hdr_file_name, "r")
command_string = str(f.readline()).split("{EOL}")
#cleaning the command list
def command_clean(command_string):
    for i in command_string:
        if (i == "" ):
            command_string.remove(i)

#cleaning up file name
def clean_file_name(name):
    name = name.replace('"', "")
    return name

#creating a copy of the specified file and renaming it
def copy_rename(file_name, file_to_name):
    file_path = zip_location + "\\" #file location where it will be renamed and stored.
    os.rename(file_path + file_to_name,file_path + file_name)

#extracting and separating the file name and file to be renamed (delimiter is the | symbol)
def command_extract(command_string):
    for s in command_string:
        sep = s.split("|")
        cmd1 = sep[2].split("\\")[-1]
        cmd2 = sep[1].strip('"')
        file_name = clean_file_name(cmd1)
        copy_rename(file_name,cmd2)
        command_clean(command_string)
command_extract(command_string)
print('不报错就成功了')

把脚本拷贝到D:\lob\DATA_TABLE目录下,取名export_data_3column.py

在cmd中登录到该目录下

图片

执行脚本

图片

文件太少了,一闪而过。再检查目录,blob文件己经变成实际的文件名,并可以正常打开查看了。

图片

3、方法2

--方法2,官方文档上说的另1个SQLCL+JS脚本

SQLcl可以认为是SQLPlus的新版本,基于Oracle SQL Developer中的脚本引擎,并附加到一个基于java的命令行界面。除了在命令行上提供更现代的工作方式之外,SQLcl还引入了SQLPlus本身所缺少的新命令和特性。

如何获取SQLcl?

JS脚本一定要在sqlcl下执行!!!

在https://www.oracle.com/database/technologies/appdev/sqlcl.html进行下载,下载后,解压到D盘目录下d:\sqlcl

图片

说明一下,运行sqlcl要用JAVA支持,不要下最新版本的JAVA,我试了就出乱码。要用这个版本没毛病,对应的安装包名

jdk-11.0.19_windows-x64_bin.exe

图片

安装JAVA后,配置下JAVA_HOME、配置下系统PATH变量,顺便把sqlcl的bin目录也添加进去,我就不赘述了相信大家都会

图片

配置成功之后,把js脚本放到D:\lob\DATA_TABLE目录下。

图片

脚本内容如下:

script
// issue the SQL
 
var binds = {}
var  ret = util.executeReturnList('select id,file_name,content from table_log_test',binds);
 
// loop the results
for (i = 0; i < ret.length; i++) {
  // debug IS nice
  ctx.write( ret[i].ID  + "\t" + ret[i].FILE_NAME+ "\n");
 
  // GET the BLOB stream
  var blobStream =  ret[i].CONTENT.getBinaryStream(1);
 
  // GET the path/file handle TO WRITE TO
  var path = java.nio.file.FileSystems.getDefault().getPath(ret[i].FILE_NAME);
 
  // dump the file stream TO the file
  java.nio.file.Files.copy(blobStream,path);
 
}
/
!dir

如果你的环境不同看一下说明,注意修改他里的的列名对应你的名称

The file name the blob column names can be changed in the query, but then you’ll ALSO need to change the CONTENT and FILE_NAME attributes for the ret[i] array mentioned on lines 10, 13, & 16.

同样cmd切换到D:\lob\DATA_TABLE目录下,先执行

sql scott/tigger@192.168.100.20:1521/orcl

登录到数据库

图片

@js_blob.sql执行脚本

图片

执行成功后,显示如下, 文件可以正常查看,问题是文件数量翻倍了。。。。

图片

至此演示结束

4、测试中遇到的坑

坑的地方有2个

第1个是python脚本要严格按照顺序执行,如果你的数据表不是按这个顺序,你可select 调整一下顺序再导出来(这里也可以跟据查询结果筛选文件),然后再按脚本执行,否则你就要修改脚本里的改名规则。

第2个就是写JS的大佬文档里原文FOR用的大写,我研究了好几个小时,一直报i=0;错误,

图片

我后来 才发现下面评论区有人指出错误。。。。。早知先看评论了。哎

图片

文档参考

如何使用sqldeveloper导出blob
https://www.thatjeffsmith.com/archive/2014/05/exporting-multiple-blobs-with-oracle-sql-developer/#:~:text=Open%20the%20Cart%20This%20is%20easy%2C%20just%20access,don%E2%80%99t%20want%20included.%20Click%20the%20%E2%80%98Export%20Cart%E2%80%99%20button

使用sqlcl+js脚本还原真实文件名
https://www.thatjeffsmith.com/archive/2020/07/using-sqlcl-to-write-out-blobs-to-files-in-20-lines-of-js/

官方文档How to Export Multiple BLOB Data, Each To Their Respective Filename (Doc ID 2753958.1)
https://support.oracle.com/knowledge/Middleware/2753958_1.html

也欢迎关注我的公众号【徐sir的IT之路】,一起学习!
————————————————————————————
公众号:徐sir的IT之路
CSDN :https://blog.csdn.net/xxddxhyz?type=blog
墨天轮:https://www.modb.pro/u/3605
PGFANS:https://www.pgfans.cn/user/home?userId=5568
————————————————————————————

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐sir(徐慧阳)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值