Oracle中如何查询无长度限制的完整CLOB列数据?
Great question! Let's break down why your current approach hits length limits, then walk through reliable solutions to retrieve the full CLOB content every time.
Why Your Current Query Truncates the CLOB
The core issue with DBMS_LOB.substr(DATAS, dbms_lob.getlength(DATAS)) is that DBMS_LOB.substr returns a VARCHAR2 type, which has hard length constraints in Oracle:
- In standard SQL contexts,
VARCHAR2maxes out at 4000 bytes (or 32767 bytes if you've enabled extended data types withMAX_STRING_SIZE = EXTENDED). - Even if you specify the full length of the CLOB, the result gets truncated to fit within
VARCHAR2's limits.
When you run select DATAS from AutorisationDoc directly, you're fetching the raw CLOB object itself—not converting it to a string. Your client tool handles the CLOB natively, so it can pull the entire content without truncation.
Solutions to Get Full CLOB Content
1. Query the CLOB Column Directly (With Client Tool Tweaks)
If you need to fetch the CLOB alongside other columns, skip DBMS_LOB.substr entirely and adjust your client tool's settings to handle large CLOBs:
select contentType, name, DATAS as doc from AutorisationDoc where AUTORIS_DOC = '62119367419202074';
Tweak these settings based on your tool:
- SQLPlus: Set the
LONGparameter to a value larger than your CLOB's size (max is 2GB):SET LONG 1000000; -- Adjust to match your CLOB's expected max length SET LONGCHUNKSIZE 1000000; - SQL Developer: Go to
Tools > Preferences > Database > Advancedand setCLOB fetch sizetoUnlimitedor a large number. - Toad: Navigate to
View > Toad Options > Data Grids > Dataand increase theMaximum bytes to retrieve for CLOBvalue.
2. Use PL/SQL to Read the CLOB in Chunks
If you need to process or output the CLOB programmatically, use a PL/SQL block to read the CLOB in chunks (avoiding VARCHAR2 truncation):
DECLARE v_full_clob CLOB; v_current_offset NUMBER := 1; v_chunk_size CONSTANT NUMBER := 32767; -- Max VARCHAR2 length in PL/SQL v_chunk VARCHAR2(32767); BEGIN -- Fetch the CLOB into a variable SELECT DATAS INTO v_full_clob FROM AutorisationDoc WHERE AUTORIS_DOC = '62119367419202074'; -- Read and output the CLOB in chunks LOOP DBMS_LOB.READ( lob_loc => v_full_clob, amount => v_chunk_size, offset => v_current_offset, buffer => v_chunk ); DBMS_OUTPUT.PUT_LINE(v_chunk); v_current_offset := v_current_offset + v_chunk_size; EXIT WHEN v_current_offset > DBMS_LOB.GETLENGTH(v_full_clob); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('No matching record found.'); END; /
Before running this, enable unlimited server output:
SET SERVEROUTPUT ON SIZE UNLIMITED;
3. Export the CLOB to a File (Optional)
If you need to save the CLOB content to a file, use UTL_FILE in PL/SQL to write chunks directly to disk:
DECLARE v_full_clob CLOB; v_current_offset NUMBER := 1; v_chunk_size CONSTANT NUMBER := 32767; v_chunk VARCHAR2(32767); v_file_handle UTL_FILE.FILE_TYPE; BEGIN SELECT DATAS INTO v_full_clob FROM AutorisationDoc WHERE AUTORIS_DOC = '62119367419202074'; -- Open a file (replace directory and filename with your own) v_file_handle := UTL_FILE.FOPEN('YOUR_DIRECTORY', 'output_doc.txt', 'W'); LOOP DBMS_LOB.READ(v_full_clob, v_chunk_size, v_current_offset, v_chunk); UTL_FILE.PUT(v_file_handle, v_chunk); v_current_offset := v_current_offset + v_chunk_size; EXIT WHEN v_current_offset > DBMS_LOB.GETLENGTH(v_full_clob); END LOOP; UTL_FILE.FCLOSE(v_file_handle); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('No matching record found.'); WHEN OTHERS THEN IF UTL_FILE.IS_OPEN(v_file_handle) THEN UTL_FILE.FCLOSE(v_file_handle); END IF; RAISE; END; /
Note: You'll need to create a directory object in Oracle first and grant write permissions to your user.
内容的提问来源于stack exchange,提问作者M.SAM SIM

