programing

기본 64 CLOB에 Oracle BLOB 연결

css3 2023. 9. 12. 20:11

기본 64 CLOB에 Oracle BLOB 연결

오라클 BLOB를 Base64 CLOB로 원고로 변환할 수 있습니까?

예:

CREATE TABLE test
(
image BLOB,
imageBase64 CLOB
);

INSERT INTO test(image)
VALUES (LOAD_FILE('/full/path/to/new/image.jpg'));

UPDATE test SET imageBase64 = UTL_ENCODE.base64_encode(image);

commit;

나는 그 일을 하기 위해 기능/저장 프로시저를 추가할 수 있다는 것을 알고 있습니다.성능적인 측면이 매우 중요하기 때문에 CLOB에 데이터를 직접 밀어넣어 32K 한계를 극복할 수 있는 방법이 있는지 문의드립니다.

여기서 얻은 이 기능이 작동할 것입니다.

CREATE OR REPLACE FUNCTION base64encode(p_blob IN BLOB)
  RETURN CLOB
-- -----------------------------------------------------------------------------------
-- File Name    : http://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;
/

그러면 업데이트는 다음과 같이 보일 수 있습니다.

UPDATE test SET imageBase64 = base64encode(image);

DBMS_LOB 기능으로 기능을 최적화해야 할 수도 있습니다.연결 연산자 대신 APPLD입니다.성능에 문제가 있으면 한 번 해보세요.

저장된 Procs가 사용자에게 실행 가능한 대안이 될 수 있음에도 불구하고, 문제에 대한 한 가지 가능한 해결책을 제시합니다.

그 멋진 를 base64encode()팀 홀의 기능이 수술에 들어간 겁니다

create or replace procedure base64encode
    ( i_blob                        in blob
    , io_clob                       in out nocopy clob )
is
    l_step                          pls_integer := 22500; -- make sure you set a multiple of 3 not higher than 24573
    l_converted                     varchar2(32767);

    l_buffer_size_approx            pls_integer := 1048576;
    l_buffer                        clob;
begin
    dbms_lob.createtemporary(l_buffer, true, dbms_lob.call);

    for i in 0 .. trunc((dbms_lob.getlength(i_blob) - 1 )/l_step) loop
        l_converted := utl_raw.cast_to_varchar2(utl_encode.base64_encode(dbms_lob.substr(i_blob, l_step, i * l_step + 1)));
        dbms_lob.writeappend(l_buffer, length(l_converted), l_converted);

        if dbms_lob.getlength(l_buffer) >= l_buffer_size_approx then
            dbms_lob.append(io_clob, l_buffer);
            dbms_lob.trim(l_buffer, 0);
        end if;
    end loop;

    dbms_lob.append(io_clob, l_buffer);

    dbms_lob.freetemporary(l_buffer);
end;

여기서 "꼼수"는 프로시저/기능 호출 시 지속적인 LOB 로케이터를 직접 사용하는 것입니다.왜 "집요"?LOB를 반환하는 함수를 생성하면 백그라운드에서 임시 LOB가 생성되므로 TEMP 디스크/메모리 사용량과 LOB 콘텐츠 복사가 포함됩니다.대형 LOB의 경우 성능 히트를 의미할 수 있습니다.이 작업을 최대한 수행해야 하는 요구 사항을 충족하려면 이러한 TEMP 공간 사용을 피해야 합니다.따라서 이 방법을 사용하려면 함수 대신 저장 프로시저를 사용해야 합니다.

그런 다음, 물론 절차에 영구 LOB 로케이터를 공급해야 합니다.저장 프로시저를 사용하여 이 작업을 다시 수행해야 합니다. 예를 들어 빈 LOB를 테이블에 먼저 삽입한 다음 새로 생성된 LOB 로케이터를 base64 인코딩 루틴에 제공하는 경우...

create or replace procedure load_and_encode_image
    ( i_file_name       in varchar2 )
is
    l_input_bfile       bfile := bfilename('DIR_ANYTHING', i_file_name);
    l_image_base64_lob  test.imageBase64%type;
    l_image_raw         test.image%type;
begin
    insert into test(image, imageBase64)
    values (empty_blob(), empty_clob())
    returning image, imageBase64
    into l_image_raw, l_image_base64_lob;

    begin
        dbms_lob.fileopen(l_input_bfile);
        dbms_lob.loadfromfile(
            dest_lob => l_image_raw,
            src_lob => l_input_bfile,
            amount => dbms_lob.getlength(l_input_bfile)
        );
        dbms_lob.fileclose(l_input_bfile);
    exception
        when others then
            if dbms_lob.fileisopen(l_input_bfile) = 1 then
                dbms_lob.fileclose(l_input_bfile);
            end if;
            raise;
    end;

    base64encode(
        i_blob => l_image_raw,
        io_clob => l_image_base64_lob
    );
end;

참고: 물론 작은 파일만 기본으로 인코딩(실제 크기는 PGA 설정에 따라 다릅니다. DBA에 대한 질문입니다.)하는 경우 함수 기반 접근 방식은 이 절차 기반 접근 방식과 동일하게 수행될 수 있습니다.Base64 - 제 노트북에 있는 200MB 파일을 인코딩하는 데 function+update 접근 방식에서는 55초, procedure 접근 방식에서는 14초가 걸렸습니다.꼭 스피드 악마는 아니니까 당신의 요구에 맞는 것을 고르세요.

참고: 절차 기반 접근 방식은 루프의 메모리 청크에 파일을 읽어들이고, base64는 청크를 메모리 청크의 다른 청크에 인코딩하여 타겟 영구 LOB에 추가함으로써 더욱 속도를 높일 수 있다고 생각합니다.이렇게 하면 전체를 다시 읽지 않도록 함으로써 워크로드를 더욱 쉽게 처리할 수 있습니다.test.image용에 :base64encode()절차.

저는 자바 저장 프로시저를 사용하여 직장에서도 이와 같은 문제를 해결했습니다.Base64를 인코딩/디코딩하는 기능은 기본적으로 Java에 내장되어 있기 때문에, 단순히 Java 메서드를 얇게 랩핑하는 Oracle 함수를 작성하는 것이 잘 작동하고 몇 번 실행하자마자 고성능이므로, 이러한 접근 방식에는 VARCHAR2의 청크/컨티네이션이 없습니다.HotSpot JVM은 Java proc를 하위 코드(C 저장 함수와 같은 고성능)로 컴파일합니다.이 답변은 나중에 수정해서 자바 코드에 대한 자세한 내용을 추가하겠습니다.

하지만 한 걸음만 뒤로 물러나기 위해, 왜 이 데이터를 BLOB와 Base64 Encoded(CLOB) 둘 다로 저장하고 있는지 질문해 보십시오.후자의 형식으로 데이터를 소비하고 싶어하는 고객이 있어서 그런가요?BLOB 포맷만 저장하고 싶습니다.한 가지 이유는 base64 인코딩된 버전이 원래 바이너리 BLOB의 두 배 크기가 될 수 있기 때문에 둘 다 저장한다는 것은 스토리지의 3배를 의미합니다.

기능을 것입니다. 에서 한 로 만의 을 가 만의 을 가 .base64_encode()이진 --> base64를 인코딩한 다음 이 함수를 사용하여 쿼리 시간에 바로 base64를 인코딩합니다(가격이 비싸지 않습니다).트서과은을게다ge게m,y/트션udne/을ect은SELECT base64_encode(image) FROM test WHERE ...

수 즉, COTS 가 기능하지 않는 를 사용하고 있으므로), 계산된 Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ 계산된 컴퓨터가 포함된 테이블의 가상(컴퓨팅) 열을 사용하여 해당 응용 프로그램 코드를 추상화할 수 있습니다.base64_encode(image)된 CLOB를. 인코딩된 CLOB를 물리적으로 저장하지 않고 쿼리 시간에 생성한다는 점에서 보기와 같은 기능을 합니다.어떤 고객에게도 물리적인 열을 읽고 있지 않다고 말할 수 없습니다.이점은 BLOB)를으로 업데이트된다는 것입니다.jpg(BLOB)는 "CLOB"입니다.거대한 BLOB 배치를 삽입/업데이트/삭제해야 하는 경우 redo/archive 로그 볼륨의 66%를 모든 CLOB를 처리할 필요가 없습니다.

마지막으로 성능을 위해 SecureFile LOB(BLOB와 CLOB 모두)를 사용하고 있는지 확인합니다.그들은 정말로 모든 면에서 훨씬 더 빠르고 더 좋습니다.

업데이트 - 적어도 자바 저장 프로시저를 사용하여 반대의 작업을 수행하는 버전(베이스64 인코딩 CLOB를 바이너리 BLOB 버전으로 변환) 내 코드를 찾았습니다.역을 쓰는 것은 그리 어렵지 않을 것입니다.

--DROP FUNCTION base64_decode ;
--DROP java source base64;

-- This is a PLSQL java wrapper function
create or replace
FUNCTION base64_decode (
   myclob clob)
   RETURN blob
AS LANGUAGE JAVA
   NAME 'Base64.decode (
            oracle.sql.CLOB) 
            return oracle.sql.BLOB';
/

-- The Java code that base64 decodes a clob and returns a blob.
create or replace and compile java source named base64 as
import java.sql.*;
import java.io.*;
import oracle.sql.*;
import sun.misc.BASE64Decoder;
import oracle.jdbc.driver.*;

public class Base64 {

public static oracle.sql.BLOB decode(oracle.sql.CLOB  myBase64EncodedClob)
  {

    BASE64Decoder base64   = new BASE64Decoder();
    OutputStream  outstrm  = null;
    oracle.sql.BLOB myBlob = null;
    ByteArrayInputStream instrm = null;

    try
    {
      if (!myBase64EncodedClob.equals("Null"))
      {
        Connection conn = new OracleDriver().defaultConnection();
        myBlob = oracle.sql.BLOB.createTemporary(conn, false,oracle.sql.BLOB.DURATION_CALL);
        outstrm = myBlob.getBinaryOutputStream();
        ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();

        InputStream in = myBase64EncodedClob.getAsciiStream();
        int c;
        while ((c = in.read()) != -1)
        {
          byteOutStream.write((char) c);
        }

        instrm = new ByteArrayInputStream(byteOutStream.toByteArray());

        try  // Input stream to output Stream
        {
          base64.decodeBuffer(instrm, outstrm);
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }

        outstrm.close();
        instrm.close();
        byteOutStream.close();
        in.close();
        conn.close();
      }

    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    return myBlob;

  }  // Public decode

} // Class Base64
;
/

특수 문자(이 문제가 없는 경우)에서 작동하는 가장 쉬운 방법은 dbms_lob.convert to clob을 사용하는 것입니다.

캡슐화 프로시저 만들기:

CREATE OR REPLACE FUNCTION blob2clob(blob_i IN BLOB) RETURN CLOB IS
  l_clob         CLOB;
  l_dest_offset  NUMBER := 1;
  l_src_offset   NUMBER := 1;
  l_amount       INTEGER := dbms_lob.lobmaxsize;
  l_clob_csid    NUMBER := nls_charset_id('WE8ISO8859P15'); --dbms_lob.default_csid;
  l_lang_context INTEGER := dbms_lob.default_lang_ctx;
  l_warning      INTEGER;
BEGIN
  ---------------------------
  -- Create Temporary BLOB --
  ---------------------------
  dbms_lob.createtemporary(lob_loc => l_clob,
                           cache   => TRUE);
  --------------------------
  -- Convert CLOB to BLOB --
  --------------------------
  dbms_lob.converttoclob(dest_lob     => l_clob,
                         src_blob     => blob_i,
                         amount       => l_amount,
                         dest_offset  => l_dest_offset,
                         src_offset   => l_src_offset,
                         blob_csid    => l_clob_csid,
                         lang_context => l_lang_context,
                         warning      => l_warning);
  --
  RETURN l_clob;
END blob2clob;

그러면 다음을 사용할 수 있습니다.

blob2clob(utl_encode.base64_encode(image))

언급URL : https://stackoverflow.com/questions/29155620/oracle-blob-to-base64-clob