【问题标题】:How convert CLOB to BLOB in Oracle?如何在 Oracle 中将 CLOB 转换为 BLOB?
【发布时间】:2020-10-16 07:26:41
【问题描述】:

首先,我将图像的 BLOB 转换为 CLOB,然后将该 CLOB 转换回 BLOB。我看不到重新转换的图像。我该如何解决这个问题?

blob_to_clob 函数:

CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB) RETURN CLOB AS
  v_clob CLOB;
  v_varchar VARCHAR2(32767);
  v_start PLS_INTEGER := 1;
  v_buffer PLS_INTEGER := 32767;
BEGIN
  DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
  FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
  LOOP
    v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
    DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
    v_start := v_start + v_buffer;
  END LOOP;
  RETURN v_clob;
END blob_to_clob;

clob_to_blob 函数:

CREATE OR REPLACE FUNCTION clob_to_blob2(p_clob IN CLOB) RETURN BLOB IS
  v_blob BLOB;
  v_offset NUMBER DEFAULT 1;
  v_amount NUMBER DEFAULT 4096;
  v_offsetwrite NUMBER DEFAULT 1;
  v_amountwrite NUMBER;
  v_buffer VARCHAR2(4096 CHAR);
BEGIN dbms_lob.createtemporary(v_blob, TRUE);
  Begin
    LOOP
      dbms_lob.READ (lob_loc => p_clob,
        amount  => v_amount,
        offset  => v_offset,
        buffer  => v_buffer);

      v_amountwrite := utl_raw.length (r => utl_raw.cast_to_raw(c => v_buffer));

      dbms_lob.WRITE (lob_loc => v_blob,
        amount  => v_amountwrite,
        offset  => v_offsetwrite,
        buffer  => utl_raw.cast_to_raw(v_buffer));

      v_offsetwrite := v_offsetwrite + v_amountwrite;

      v_offset := v_offset + v_amount;
      v_amount := 4096;
    END LOOP;
  EXCEPTION
    WHEN no_data_found THEN
    NULL;
  End;
  RETURN v_blob;
END clob_to_blob2;

【问题讨论】:

  • 如何将 BLOB 转换为 CLOB?特别是在 UTF-8 的情况下,您可能有许多将被删除的无效“字符”。是在谈论Base64 编码吗?
  • 您不能这样做,就像您可以将吐司放回烤面包机并按“untoast”一样。您在第一次转换中丢失了无法在第二次转换中恢复的信息。

标签: oracle plsql


【解决方案1】:

这样的代码将执行最少的重新编码:

create or replace function clob2blob(AClob CLOB) return BLOB is
  Result BLOB;
  o1 integer;
  o2 integer;
  c integer;
  w integer;
begin
  o1 := 1;
  o2 := 1;
  c := 0;
  w := 0;
  DBMS_LOB.CreateTemporary(Result, true);
  DBMS_LOB.ConvertToBlob(Result, AClob, length(AClob), o1, o2, 0, c, w);
  return(Result);
end clob2blob;
/

但是 CLOB 不能正确包含所有没有像 Base64 这样的编码的 Image 数据

【讨论】:

    【解决方案2】:

    你可以使用:

    CREATE FUNCTION clob_to_blob(
      value            IN CLOB,
      charset_id       IN INTEGER DEFAULT DBMS_LOB.DEFAULT_CSID,
      error_on_warning IN NUMBER  DEFAULT 0
    ) RETURN BLOB
    IS
      result       BLOB;
      dest_offset  INTEGER := 1;
      src_offset   INTEGER := 1;
      lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
      warning      INTEGER;
      warning_msg  VARCHAR2(50);
    BEGIN
      DBMS_LOB.CreateTemporary(
        lob_loc => result,
        cache   => TRUE
      );
    
      DBMS_LOB.CONVERTTOBLOB(
        dest_lob     => result,
        src_clob     => value,
        amount       => LENGTH( value ),
        dest_offset  => dest_offset,
        src_offset   => src_offset,
        blob_csid    => charset_id,
        lang_context => lang_context,
        warning      => warning
      );
      
      IF warning != DBMS_LOB.NO_WARNING THEN
        IF warning = DBMS_LOB.WARN_INCONVERTIBLE_CHAR THEN
          warning_msg := 'Warning: Inconvertible character.';
        ELSE
          warning_msg := 'Warning: (' || warning || ') during CLOB conversion.';
        END IF;
        
        IF error_on_warning = 0 THEN
          DBMS_OUTPUT.PUT_LINE( warning_msg );
        ELSE
          RAISE_APPLICATION_ERROR(
            -20567, -- random value between -20000 and -20999
            warning_msg
          );
        END IF;
      END IF;
    
      RETURN result;
    END clob_to_blob;
    /
    

    【讨论】:

      猜你喜欢
      • 2012-10-02
      • 2018-07-15
      • 1970-01-01
      • 2018-08-05
      • 1970-01-01
      • 2012-10-03
      • 2017-01-17
      • 1970-01-01
      • 2017-05-22
      相关资源
      最近更新 更多