기본 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
'programing' 카테고리의 다른 글
MariaDB 사용자 정의 변수에 휴지통 값이 있는 이유는 무엇입니까? (0) | 2023.09.12 |
---|---|
'requestReview()'는 iOS 14.0에서 더 이상 사용되지 않습니다. (0) | 2023.09.12 |
장고에서 db를 리셋하는 방법은?'reset' 명령을 찾을 수 없음 오류가 발생함 (0) | 2023.09.12 |
스프링 부트 액추에이터의 트레이스에 JSON 응답 바디를 포함하는 방법은? (0) | 2023.09.12 |
MVC 4에서 위조 방지 쿠키 토큰과 폼 필드 토큰이 일치하지 않습니다. (0) | 2023.09.12 |