Oracle SQLでBLOBからテキストコンテンツを取得する方法


112

SQLコンソールからOracle BLOBの内容を確認しようとしています。

やや大きなテキストの本文が含まれていることを知っているので、テキストだけを見たいのですが、次のクエリは、そのフィールドにBLOBがあることを示しているだけです。

select BLOB_FIELD from TABLE_WITH_BLOB where ID = '<row id>';

私が得ている結果は私が期待したものとはかなり異なります:

    BLOB_FIELD
    -----------------------
    oracle.sql.BLOB@1c4ada9

では、BLOBをテキスト表現に変換するために、どのような魔法の呪文を実行できるでしょうか。

PS:BLOBの内容をSQLコンソール(Eclipse Data Tools)から見ようとしています。コードでは使用していません。

回答:


141

まず、バイナリデータ用に設計されたBLOBではなくCLOB / NCLOB列にテキストを格納することができます(ところで、クエリはCLOBで機能します)。

次のクエリでは、すべての文字セットに互換性がある場合(最大でBLOBに格納されているテキストのCS、VARCHAR2に使用されているデータベースのCS)、BLOB内のテキストの最初の32767文字(多くても)を確認できます。

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';

3
残念ながら、私はデータベーススキーマを制御していません-ブロブをのぞくだけです...とにかくありがとう。
Roland Tepp

Macに感謝します。これで問題なく動作します---しかし、「dbms_lob.substr」の目的は何ですか。---「select utl_raw.cast_to_varchar2(BLOB_FIELD)...」のみを使用しても同じ結果が得られるようです...?
2013

4
cast_to_varchar2は入力でRAWを受け取り(docs.oracle.com/cd/E11882_01/appdev.112/e25788/…)、長さは32767バイトに制限されています(docs.oracle.com/cd/E11882_01/appdev.112/e10472 /…)。BLOBにはサイズの制限がないため、substrは必要に応じて正しいサイズ(docs.oracle.com/cd/E11882_01/appdev.112/e25788/…)に切り捨てます。
Mac

34
機能しません-「ORA-06502:PL / SQL:数値または値のエラー:生の変数の長さが長すぎます」と表示されます。BLOB_FIELDの後に「2000,1」を置くと、最大2000文字を取得できますが、それ以上のものはありません。
マーク

2
値が4000より長い場合、SQLの文字列の最大値であるため、エラーがスローされます。substr(BLOB_FIELD、4000、1)を追加する必要があります。より長いフィールドサポートが必要な場合は、PL / SQLを使用してください(最大32000と思います)
Sonic Soul

14

以下のSQLを使用して、テーブルからBLOBフィールドを読み取ることができます。

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

BLOB列があり、XMLデータが圧縮されてテーブルに格納されている場合、データを読み取ると、一部の数値のみが表示され、実際のXMLテキストは表示されません。XMLテキストデータをテーブルから読み取るにはどうすればよいですか。
BHUVANESH MOHANKUMAR

14

SQL Developerもこの機能を提供します。

結果グリッドセルをダブルクリックし、[編集]をクリックします。

ここに画像の説明を入力してください

次に、ポップアップの右上にある[テキストとして表示](画像を表示することもできます。)

ここに画像の説明を入力してください

以上です!

ここに画像の説明を入力してください


すばらしいヒントです。ありがとうございます。
エドグラハム

7

テキストを表示するのではなく、テキスト内を検索する場合、これは機能します。

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;

ここでmy_idは何ですか?
anjanb 2017年

これは私にとっては機能しません。BLOB列があり、XMLデータが圧縮されてテーブルに格納されています。データを読み取ると、実際のXMLテキストではなく一部の数値のみが表示されます。XMLテキストを読み取るにはどうすればよいですか。テーブルからのデータ。
BHUVANESH MOHANKUMAR

3

列が圧縮されていないため、バーンの答えは私にとっては修正して機能しました。迅速で汚れたソリューション:

select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;

3

私はしばらくこれに苦労してPL / SQLソリューションを実装しましたが、後でToadで結果グリッドセルをダブルクリックするだけで、テキストの内容のエディターが表示されることに気付きました。(私はToad v11にいます)

ここに画像の説明を入力してください


1

テキストが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;

これが誰かを助けることを願っています。


1

このSQLを使用して、BLOBの最初の2000文字を取得します。

SELECT utl_raw.cast_to_varchar2(dbms_lob.substr(<YOUR_BLOB_FIELD>,2000,1)) FROM <YOUR_TABLE>;

注:これは、Oracleが長さが2000を超えるBLOBの変換を処理できないためです。


0

あなたはこれを試すことができます:

SELECT TO_CHAR(dbms_lob.substr(BLOB_FIELD, 3900)) FROM TABLE_WITH_BLOB;

ただし、4000バイトに制限されます。


-2

私のために働いた、

lcase((insert(insert(insert(insert(insert(hex(BLOB_FIELD)、9,0、 '-')、14,0、 '-')、19,0、 '-')、24,0、 '-を選択します')))TABLE_WITH_BLOBのFIELD_IDとしてID =' row id ';


これで問題が解決した場合は、OPであるOracleを使用していないため、有効なOracle構文で回答する必要があります。
APC

-4

TO_CHAR関数を使用します。

select TO_CHAR(BLOB_FIELD) from TABLE_WITH_BLOB where ID = '<row id>'

変換しNCHARNVARCHAR2CLOB、またはNCLOBデータベース・キャラクタ・セットへのデータ。返される値は常にVARCHAR2です。


SELECT DBMS_LOB.SUBSTR(BLOB_FIELD)FROM TABLE_WITH_BLOB;
Sambhav 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.