'BLOB to CLOB Conversion : Cyrillic characters are not getting converted properly

BLOB to CLOB Conversion : Cyrillic characters are not getting converted properly

Based on our product migration, I have an requirement to replace below mentioned single byte character to Double byte character in each and every record but the respective column is BLOB datatype encoded with AL32UTF8 so I'm using the below procedure to convert column from BLOB to CLOB and replace the single byte character to Double byte character and convert back to CLOB to BLOB.

NLS_CHAR--> AL32UTF8

For ex: when I tried with CL8ISO8859P5 character set in CLOB conversion function, Bulgarian data is corrupted and If I tried with AL32UTF8 character set then the respective Cyrillic character got corrupted.

select convert_to_clob(XMLRECORD) From F_TEC_OUTPUT_T

CLOB conversion with AL32UTF8 characterset:

ONE�АНУЛИРАНЕ НА ОПРОСТЕНА ФАКТУРА_�THREE

CLOB conversion with CL8ISO8859P5 characterset:

ONEўаааЃааа ааа аа ааа ааЁаЂааа аЄаааЂаЃа а_ўTHREE

select recid, dbms_lob.substr(XMLRECORD) as raw_xrec from F_TEC_OUTPUT_T

[enter image description here][1]

Please suggest the proper way to convert this.

Single byte ---> Double byte

ў --> яЃО

§ --> яЃН

ќ --> яЃМ

In RAW:

FE --> EFA3BE

FD --> EFA3BD

FC --> EFA3BC

FB --> EFA3BB

   l_clob     CLOB;
    l_dest_offset NUMBER := 1;
    l_src_offset  NUMBER := 1;
    l_lang_context NUMBER := dbms_lob.default_lang_ctx;
   l_warning   NUMBER;
  BEGIN
    dbms_lob.createtemporary(l_clob, TRUE);
    dbms_lob.converttoclob(dest_lob   => l_clob,
               src_blob   => l_blob,
               amount    => dbms_lob.lobmaxsize,
               dest_offset => l_dest_offset,
               src_offset  => l_src_offset,
               blob_csid  => nls_charset_id('CL8ISO8859P5'),
               lang_context => l_lang_context,
               warning   => l_warning);
   RETURN l_clob;
  END convert_to_clob; 

CREATE OR REPLACE FUNCTION convert_to_blob(l_clob CLOB) RETURN BLOB IS
  l_blob     BLOB;
  l_dest_offset NUMBER := 1;
  l_src_offset  NUMBER := 1;
  l_lang_context NUMBER := dbms_lob.default_lang_ctx;
  l_warning   NUMBER;
 BEGIN
  dbms_lob.createtemporary(l_blob, TRUE);
  dbms_lob.converttoblob(dest_lob   => l_blob,
              src_clob   => l_clob,
              amount    => dbms_lob.lobmaxsize,
              dest_offset => l_dest_offset,
              src_offset  => l_src_offset,
              blob_csid  => nls_charset_id('AL32UTF8'),
              lang_context => l_lang_context,
              warning   => l_warning);
  RETURN l_blob;
 END convert_to_blob;

CREATE OR REPLACE PROCEDURE convert_blob_file(p_tname in varchar2,parallel_no_cnt in number default 1,record_cmt_cnt in number default 1) IS
TYPE cur_typ IS REF CURSOR;
getcursordata cur_typ;
ConversionRecID VARCHAR2(2000);
BinaryValueSource BLOB;
BinaryValueDest BLOB;
BinaryValueTemp CLOB;
cnt NUMBER := 1;
Dicttablename VARCHAR2(2000);
Marker_R_count NUMBER := 0;
XmlrecordTemp CLOB;
Selectstring VARCHAR2(2000);
select_table_query VARCHAR2(1000):= 'SELECT /*+ PARALLEL('''||parallel_no_cnt||''') */ RECID,XMLRECORD FROM ' || p_tname || ' WHERE XMLRECORD IS NOT NULL';
BEGIN
  OPEN getcursordata FOR select_table_query;
  LOOP
    FETCH getcursordata INTO ConversionRecID, BinaryValueSource;
    EXIT WHEN getcursordata%NOTFOUND;
   BinaryValueTemp := convert_to_clob(BinaryValueSource);
    BinaryValueTemp := REPLACE(BinaryValueTemp,CHR(53662),CHR(15705022)); -- @FM Separator
    BinaryValueTemp := REPLACE(BinaryValueTemp,CHR(49831),CHR(15705021)); -- @VM Separator
    BinaryValueTemp := REPLACE(BinaryValueTemp,CHR(53660),CHR(15705020)); -- @SM Separator
    BinaryValueTemp := REPLACE(BinaryValueTemp,CHR(53659),CHR(15705019)); -- @TM Separator
    BinaryValueDest := convert_to_blob(BinaryValueTemp);
    EXECUTE IMMEDIATE 'UPDATE /*+ PARALLEL('''||parallel_no_cnt||''') */'||p_tname||' SET XMLRECORD = :v1 WHERE RECID= :v2' USING BinaryValueDest,ConversionRecID;
IF cnt=record_cmt_cnt THEN
      cnt:=1;
      COMMIT;
    ELSE
      cnt := cnt + 1;
    END IF;
  END LOOP;
  CLOSE getcursordata;
  DBMS_OUTPUT.PUT_LINE('Time------'||to_char(sysdate, 'HH24:MI:SS'));
END;```


  [1]: https://i.stack.imgur.com/t9w19.jpg


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source