背景

客户生产系统有张表存储流程bpmn文件,由于某些原因,更新程序找不到,因此只能连接数据库直接更新字段,数据库是oracle数据库,字段类型是blob。

PL/SQL Developer

一开始通过PL/SQL Developer工具进行编辑,bpmn文件使用UTF-8编码,但是在工具中查看是乱码,因此不能直接编辑

image-20220515180315367

可以点工具上面保存按钮将数据导出到本地文件,导出后打开是正常的,于是本地修改后通过PL/SQL Developer重新导入,但在程序里面读取中文却是乱码的(程序使用java编写),不同工具间转换,编码乱掉也见怪不怪,也不想去折腾工具,想着这种工具问题折腾了也没什么结果。

base64

最万无一失的办法就是导出原始文件,在本地编辑后也导入原始文件,于是想到通过base64作为中间编码进行转换,具体过程为

blob->base64编码->base64解码->获得原始文件->修改文件->base64编码->数据库base64解码->blob

从google上找到Tim Hall大神写的blob和base64的转换程序

base64encode.sql
CREATE OR REPLACE FUNCTION base64encode(p_blob IN BLOB)
  RETURN CLOB
-- -----------------------------------------------------------------------------------
-- File Name    : https://oracle-base.com/dba/miscellaneous/base64encode.sql
-- Author       : Tim Hall
-- Description  : Encodes a BLOB into a Base64 CLOB.
-- Last Modified: 09/11/2011
-- -----------------------------------------------------------------------------------
IS
  l_clob CLOB;
  l_step PLS_INTEGER := 12000; -- make sure you set a multiple of 3 not higher than 24573
BEGIN
  FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_blob) - 1 )/l_step) LOOP
    l_clob := l_clob || UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(p_blob, l_step, i * l_step + 1)));
  END LOOP;
  RETURN l_clob;
END;
/
base64decode.sql
CREATE OR REPLACE FUNCTION base64decode(p_clob CLOB)
  RETURN BLOB
-- -----------------------------------------------------------------------------------
-- File Name    : https://oracle-base.com/dba/miscellaneous/base64decode.sql
-- Author       : Tim Hall
-- Description  : Decodes a Base64 CLOB into a BLOB
-- Last Modified: 09/11/2011
-- -----------------------------------------------------------------------------------
IS
  l_blob    BLOB;
  l_raw     RAW(32767);
  l_amt     NUMBER := 7700;
  l_offset  NUMBER := 1;
  l_temp    VARCHAR2(32767);
BEGIN
  BEGIN
    DBMS_LOB.createtemporary (l_blob, FALSE, DBMS_LOB.CALL);
    LOOP
      DBMS_LOB.read(p_clob, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt;
      l_raw    := UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(l_temp));
      DBMS_LOB.append (l_blob, TO_BLOB(l_raw));
    END LOOP;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      NULL;
  END;
  RETURN l_blob;
END;
/

着两个funtion可以实现base64和blob之间的转换,base64文本是通过clob字段进行存储。将以上两个sql在oracle中执行即可。

具体步骤如下

  • 获得blob的base64文本
select base64encode(t.bytes_) from act_ge_bytearray t where t.id_=6386864;
  • 拷贝到本地文本文件中,然后通过base64工具进行还原,如果是mac,可以直接通过base64命令进行解码
base64 -Di  base64.txt >process.xml
如果没有工具,可以通过在线工具进行解码,比如这个
  • 本地通过文本编辑工具进行编辑,编辑后重新进行编码
base64 process.xml >base64.txt
  • 数据库中创建临时表用来存储base64
create table base64_tmp(
  base64_text clob;
)
  • 通过工具PL/SQL Developer在临时表上新增一条数据,并且拷贝本地的base64保存进去
  • 通过update语句进行更新
update act_ge_bytearray t set t.bytes_=(select base64decode(tt.base64_text) from base64_tmp tt) where t.id_=6386864

总结

方法可能有点麻烦,但这是可以想到不通过代码最稳妥的方法,如果你有更好的方法(写代码不算),欢迎评论区留言。

,
Trackback

no comment untill now

Add your comment now