Làm cách nào để lấy nội dung văn bản từ BLOB trong Oracle SQL


112

Tôi đang cố gắng xem từ bảng điều khiển SQL có gì bên trong Oracle BLOB.

Tôi biết nó chứa một phần nội dung văn bản hơi lớn và tôi muốn chỉ xem văn bản, nhưng truy vấn sau chỉ cho biết rằng có một BLOB trong trường đó:

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

kết quả tôi nhận được không hoàn toàn như tôi mong đợi:

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

Vậy tôi có thể làm những câu thần chú ma thuật nào để biến BLOB thành biểu tượng văn bản của nó?

Tái bút: Tôi chỉ đang cố gắng xem nội dung của BLOB từ bảng điều khiển SQL (Công cụ dữ liệu Eclipse), không sử dụng nó trong mã.

Câu trả lời:


141

Trước hết, bạn có thể muốn lưu trữ văn bản trong các cột CLOB / NCLOB thay vì BLOB, được thiết kế cho dữ liệu nhị phân (nhân tiện, truy vấn của bạn sẽ hoạt động với CLOB).

Truy vấn sau đây sẽ cho bạn thấy 32767 ký tự đầu tiên (nhiều nhất) của văn bản bên trong đốm màu, miễn là tất cả các bộ ký tự đều tương thích (CS gốc của văn bản được lưu trữ trong BLOB, CS của cơ sở dữ liệu được sử dụng cho VARCHAR2):

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

3
Thật không may, tôi không kiểm soát lược đồ cơ sở dữ liệu - tôi chỉ cần nhìn vào đốm màu ... Nhưng dù sao cũng cảm ơn.
Roland Tepp

Cảm ơn Mac, nó hoạt động tốt --- Nhưng mục đích của "dbms_lob.substr" đó là gì? --- Chỉ sử dụng "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." dường như cho tôi kết quả tương tự ...?
Rop

4
cast_to_varchar2 nhận đầu vào RAW ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), độ dài giới hạn ở 32767 byte ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). BLOB không có giới hạn về kích thước, vì vậy, substr cắt nó thành kích thước chính xác ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) nếu cần.
Mac

34
Không hoạt động với tôi - Tôi nhận được "ORA-06502: PL / SQL: lỗi số hoặc giá trị: độ dài biến thô quá dài". Tôi có thể đặt "2000,1" sau BLOB_FIELD để nhận được tối đa 2000 ký tự, nhưng không có gì vượt quá.
Đánh dấu

2
nếu giá trị dài hơn 4000 nó sẽ tạo ra lỗi vì đó là giá trị tối đa cho các chuỗi trong sql. bạn cần thêm substr (BLOB_FIELD, 4000, 1). Nếu bạn cần hỗ trợ trường lâu hơn, hãy sử dụng PL / SQL (tôi tin là lên đến 32000)
Sonic Soul

14

Bạn có thể sử dụng SQL bên dưới để đọc Trường BLOB từ bảng.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

Tôi có cột BLOB và nơi dữ liệu XML được nén và lưu trữ trong bảng, khi tôi đọc dữ liệu, nó chỉ hiển thị một số con số chứ không phải văn bản xml thực tế, tôi phải làm gì để đọc dữ liệu văn bản XML từ bảng.
BHUVANESH MOHANKUMAR

14

SQL Developer cũng cung cấp chức năng này:

Nhấp đúp vào ô lưới kết quả và nhấp vào chỉnh sửa:

nhập mô tả hình ảnh ở đây

Sau đó, ở phần trên cùng bên phải của cửa sổ bật lên, "Xem dưới dạng văn bản" (Bạn thậm chí có thể xem hình ảnh ..)

nhập mô tả hình ảnh ở đây

Và đó là nó!

nhập mô tả hình ảnh ở đây


Đó là một mẹo tuyệt vời - cảm ơn!
Ed Graham

7

Nếu bạn muốn tìm kiếm bên trong văn bản, thay vì xem nó, điều này sẽ hoạt động:

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 ở đây là gì?
anjanb

Điều này không hiệu quả đối với tôi, tôi có cột BLOB và nơi dữ liệu XML được nén và lưu trữ trong bảng, khi tôi đọc dữ liệu, nó chỉ hiển thị một số số chứ không phải văn bản xml thực tế, tôi phải làm gì để đọc văn bản XML dữ liệu từ bảng.
BHUVANESH MOHANKUMAR

3

Câu trả lời của Barn phù hợp với tôi với sự sửa đổi vì cột của tôi không được nén. Giải pháp nhanh chóng và bẩn thỉu:

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

3

Tôi đã vật lộn với điều này trong một thời gian và triển khai giải pháp PL / SQL, nhưng sau đó nhận ra rằng trong Toad, bạn có thể chỉ cần nhấp đúp vào ô lưới kết quả và nó hiển thị một trình soạn thảo với nội dung trong văn bản. (Tôi đang sử dụng Toad v11)

nhập mô tả hình ảnh ở đây


1

Trong trường hợp văn bản của bạn được nén bên trong blob bằng thuật toán DEFLATE và nó khá lớn, bạn có thể sử dụng chức năng này để đọc nó

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;
/

Sau đó chạy chọn để nhận văn bản

SELECT read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;

Hy vọng điều này sẽ giúp một ai đó.


1

Sử dụng SQL này để lấy 2000 ký tự đầu tiên của BLOB.

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

Lưu ý: Điều này là do, Oracle sẽ không thể xử lý việc chuyển đổi BLOB dài hơn 2000.


0

Bạn có thể thử điều này:

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

Tuy nhiên, nó sẽ bị giới hạn ở 4000 byte


-2

Đã làm cho tôi,

chọn lcase ((insert (insert (insert (insert (hex (BLOB_FIELD)), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) dưới dạng FIELD_ID từ TABLE_WITH_BLOB trong đó ID =' id hàng ';


Nếu điều này hiệu quả với bạn thì bạn không sử dụng Oracle, OP là OP và đó là lý do tại sao các câu trả lời cần phải là cú pháp Oracle hợp lệ.
APC

-4

Sử dụng TO_CHARchức năng.

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

Chuyển đổi NCHAR, NVARCHAR2, CLOB, hoặc NCLOBdữ liệu đến các bộ ký tự cơ sở dữ liệu. Giá trị trả về luôn luôn VARCHAR2.


CHỌN DBMS_LOB.SUBSTR (BLOB_FIELD) TỪ TABLE_WITH_BLOB;
Sambhav
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.