Oracle SQLでBLOBからテキストコンテンツを取得する方法
質問
SQLコンソールからOracle BLOBの内部を確認しようとしています。
やや大きなテキストが含まれていることは知っているので、テキストだけを表示したいのですが、次のクエリはそのフィールドにBLOBがあることを示しているだけです。
select BLOB_FIELD from TABLE_WITH_BLOB where ID = '<row id>';
私が得ている結果は、私が期待したものとはまったく異なります:
BLOB_FIELD ----------------------- oracle.sql.BLOB@1c4ada9
では、BLOBをテキスト表現にするには、どのような魔法の呪文を使用できますか?
PS:コードで使用するのではなく、SQLコンソール(Eclipse Data Tools)からBLOBのコンテンツを見ようとしています。
解決
まず、バイナリデータ用に設計されたBLOBではなく、CLOB / NCLOB列にテキストを格納することをお勧めします(ちなみに、クエリはCLOBで機能します)。
次のクエリでは、すべての文字セットに互換性がある場合(BLOBに保存されているテキストの元のCS、VARCHAR2に使用されるデータベースのCS) ):
select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
他のヒント
以下のSQLを使用して、テーブルからBLOBフィールドを読み取ることができます。
SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
テキストを表示するのではなく、テキスト内を検索する場合、これは機能します:
with unzipped_text as (
select
my_id
,utl_compress.lz_uncompress(my_compressed_blob) as my_blob
from my_table
where my_id='MY_ID'
)
select * from unzipped_text
where dbms_lob.instr(my_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
しばらくの間これに苦労し、PL / SQLソリューションを実装しましたが、後でToadでは結果グリッドセルをダブルクリックするだけで、テキストの内容を含むエディターが表示されることに気付きました。 (Toad v11を使用しています)
私のコラムは圧縮されていないので、Barnの答えは修正してもうまくいきました。迅速で汚い解決策:
select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
これを試すことができます:
SELECT TO_CHAR(dbms_lob.substr(BLOB_FIELD, 3900)) FROM TABLE_WITH_BLOB;
ただし、4000バイトに制限されます
DEFLATEアルゴリズムを使用してblob内でテキストが圧縮され、非常に大きい場合、この関数を使用して読むことができます
CREATE OR REPLACE PACKAGE read_gzipped_entity_package AS
FUNCTION read_entity(entity_id IN VARCHAR2)
RETURN VARCHAR2;
END read_gzipped_entity_package;
/
CREATE OR REPLACE PACKAGE BODY read_gzipped_entity_package IS
FUNCTION read_entity(entity_id IN VARCHAR2) RETURN VARCHAR2
IS
l_blob BLOB;
l_blob_length NUMBER;
l_amount BINARY_INTEGER := 10000; -- must be <= ~32765.
l_offset INTEGER := 1;
l_buffer RAW(20000);
l_text_buffer VARCHAR2(32767);
BEGIN
-- Get uncompressed BLOB
SELECT UTL_COMPRESS.LZ_UNCOMPRESS(COMPRESSED_BLOB_COLUMN_NAME)
INTO l_blob
FROM TABLE_NAME
WHERE ID = entity_id;
-- Figure out how long the BLOB is.
l_blob_length := DBMS_LOB.GETLENGTH(l_blob);
-- We'll loop through the BLOB as many times as necessary to
-- get all its data.
FOR i IN 1..CEIL(l_blob_length/l_amount) LOOP
-- Read in the given chunk of the BLOB.
DBMS_LOB.READ(l_blob
, l_amount
, l_offset
, l_buffer);
-- The DBMS_LOB.READ procedure dictates that its output be RAW.
-- This next procedure converts that RAW data to character data.
l_text_buffer := UTL_RAW.CAST_TO_VARCHAR2(l_buffer);
-- For the next iteration through the BLOB, bump up your offset
-- location (i.e., where you start reading from).
l_offset := l_offset + l_amount;
END LOOP;
RETURN l_text_buffer;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('!ERROR: ' || SUBSTR(SQLERRM,1,247));
END;
END read_gzipped_entity_package;
/
次にselectを実行してテキストを取得します
SELECT read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;
これが誰かの助けになることを願っています。
私のために働いた、
select lcase((insert( インサート( インサート( insert(hex(BLOB_FIELD)、9,0、 '-')、 14,0、 '-')、 19,0、 '-')、 FIELD_IDとして24,0、 '-')))) TABLE_WITH_BLOBから ここで、ID = 'row id';
TO_CHAR
関数を使用します。
select TO_CHAR(BLOB_FIELD) from TABLE_WITH_BLOB where ID = '<row id>'
NCHAR
、 NVARCHAR2
、 CLOB
、または NCLOB
データをデータベースの文字セットに変換します。返される値は常に VARCHAR2
です。