8.2 PL/SQL API for LOBs
The DBMS_LOB
package enables you to access and make changes to LOBs in PL/SQL.
See Also:
DBMS_LOB for more information on DBMS_LOB package.Guidelines for Offset and Amount Parameters in DBMS_LOB Operations
The following guidelines apply to the offset
and amount
parameters used in the DBMS_LOB
PL/SQL package procedures:
- For character data in all formats, either in fixed-width or variable-width, the
amount
andoffset
parameters are in characters. This applies to operations onCLOB
andNCLOB
data types. - For binary data, the
offset
andamount
parameters are in bytes. This applies to operations onBLOB
data types. - When using the
DBMS_LOB.READ
procedure, theamount
parameter should be less than or equal to the size of the buffer, which is limited to 32K. However, theamount
parameter can be larger than the size of the LOB data.
Table 8-2 DBMS_LOB functions and procedures for LOBs
Category | Function/Procedure | Description |
---|---|---|
Sanity Checking | ISSECUREFILE |
Find out if the BLOB or
CLOB locator is a SecureFile
|
Open/Close | OPEN |
Open a LOB |
ISOPEN |
Check if a LOB is open | |
CLOSE |
Close the LOB | |
Read Operations | GETLENGTH |
|
GET_STORAGE_LIMIT |
||
GETCHUNKSIZE |
||
READ |
||
SUBSTR |
||
INSTR |
||
Modify Operations | WRITE |
Write data to the LOB at a specified offset |
WRITEAPPEND |
Write data to the end of the LOB | |
ERASE |
Erase part of a LOB, starting at a specified offset | |
TRIM |
Trim the LOB value to the specified shorter length | |
Operations involving multiple locators | COMPARE |
Compare all or part of the value of two LOBs |
APPEND |
Append a LOB value to another LOB | |
COPY |
Copy all or part of a LOB to another LOB | |
dst := src |
Assign LOB locator src to LOB locator dst |
|
CONVERTTOBLOB, CONVERTTOCLOB |
Converts a BLOB to a CLOB or a CLOB to a BLOB |
|
LOADCLOBFROMFILE,LOADBLOBFROMFILE |
Load BFILE data into a LOB
|
|
Operations specific to SecureFiles | GETOPTIONS |
Returns options (deduplication, compression, encryption) for SecureFiles. |
SETOPTIONS |
Sets LOB features (deduplication and compression) for SecureFiles | |
GETCONTENTTYPE |
Gets the content string for a SecureFiles. | |
SETCONTENTTYPE |
Sets the content string for a SecureFiles. | |
FRAGMENT_DELETE |
Delete the data from the LOB at the given offset for the given length | |
FRAGMENT_INSERT |
Insert the given data (< 32KBytes) into the LOB at the given offset | |
FRAGMENT_MOVE |
Move the given amount of bytes from the given offset to the new given offset | |
FRAGMENT_REPLACE |
Replace the data at the given offset with the given data (< 32kBytes) |
Example 8-1 PL/SQL API for LOBs
DECLARE
retval INTEGER;
clob1 CLOB;
clob2 CLOB;
clob3 CLOB;
blob1 BLOB;
buf VARCHAR2(32767);
buflen INTEGER := 32760;
loblen1 INTEGER;
-- Following are the variables that you need for the convertToBlob and convertToClob functions
amt NUMBER := 0;
src NUMBER := 1 ;
dst NUMBER := 1 ;
lang NUMBER := 0;
warn NUMBER;
BEGIN
SELECT ad_sourcetext INTO clob1 FROM print_media
WHERE product_id = 1 AND ad_id = 1;
-- the select statement is defined with FOR UPDATE so that we can write to it
SELECT ad_finaltext INTO clob2 FROM print_media
WHERE product_id = 1 AND ad_id =1 FOR UPDATE;
/* Note that all the writes to clob2 will get reflected in the column */
/*------------------------------------------------------------------*/
/*---------------------- Sanity Checking ---------------------------*/
/*------------------------------------------------------------------*/
if DBMS_LOB.ISSECUREFILE(clob1) = TRUE then
DBMS_OUTPUT.PUT_LINE('CLOB1 is SECUREFILE');
else
DBMS_OUTPUT.PUT_LINE('CLOB1 is BASICFILE');
end if;
/*------------------------------------------------------------------*/
/*----------------------- Open -------------------------------------*/
/*------------------------------------------------------------------*/
/* Open clob1 for READs and clob2 for WRITES */
DBMS_LOB.OPEN(clob1, DBMS_LOB.LOB_READONLY);
DBMS_LOB.OPEN(clob2, DBMS_LOB.LOB_READWRITE);
/*------------------------------------------------------------------*/
/*-------------------- Reading from a LOB --------------------------*/
/*------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('storage limit : ' || dbms_lob.get_storage_limit(clob1));
DBMS_OUTPUT.PUT_LINE('chunk size : ' || dbms_lob.getchunksize(clob1));
loblen1 := DBMS_LOB.GETLENGTH(clob1);
DBMS_OUTPUT.PUT_LINE('length : ' || loblen1);
DBMS_LOB.READ(clob1, buflen, 1, buf);
DBMS_OUTPUT.PUT_LINE('read : LOB data : ' || buf);
DBMS_OUTPUT.PUT_LINE('New buflen : ' || buflen);
DBMS_OUTPUT.PUT_LINE('substr : ' || dbms_lob.substr(clob1, 30, 1));
DBMS_OUTPUT.PUT_LINE('instr : ' ||
DBMS_LOB.INSTR(clob1, 'review of the document', 1, 3));
/*------------------------------------------------------------------*/
/*-------------------- Modifying a LOB -----------------------------*/
/*------------------------------------------------------------------*/
DBMS_LOB.WRITE(clob2, buflen, 10, buf);
DBMS_LOB.WRITEAPPEND(clob2, buflen, buf);
buflen := 10;
DBMS_LOB.ERASE(clob2, buflen, 10);
DBMS_LOB.TRIM(clob2, 50);
/* Print the LOB just modified */
buflen := 32760;
DBMS_LOB.READ(clob2, buflen, 1, buf);
DBMS_OUTPUT.PUT_LINE('read : LOB data : ' || buf);
DBMS_OUTPUT.PUT_LINE('New buflen : ' || buflen);
/* Error because clob1 is open in READ mode */
-- DBMS_LOB.WRITE(clob1, buflen, 10, buf);
/*------------------------------------------------------------------*/
/*------------- Operations involving 2 locators ---------------------*/
/*------------------------------------------------------------------*/
retval := DBMS_LOB.COMPARE(clob1, clob2, 100, 1, 1);
if (retval < 0) then
DBMS_OUTPUT.PUT_LINE('clob1 is smaller');
elsif (retval = 0) then
DBMS_OUTPUT.PUT_LINE('both clobs are equal');
else
DBMS_OUTPUT.PUT_LINE('clob1 is larger');
end if;
DBMS_OUTPUT.PUT_LINE('length before append: ' || DBMS_LOB.GETLENGTH(clob2));
DBMS_LOB.APPEND(clob2, clob1);
DBMS_OUTPUT.PUT_LINE('length after append: ' || DBMS_LOB.GETLENGTH(clob2));
DBMS_OUTPUT.PUT_LINE('----------- LOB COPY operation --------');
DBMS_LOB.COPY(clob2, clob1, loblen1, 100, 1);
DBMS_OUTPUT.PUT_LINE('length after copy: ' || DBMS_LOB.GETLENGTH(clob2));
/*------------------------------------------------------------------*/
/*------------------- Convert CLOB to a BLOB -----------------------*/
/*------------------------------------------------------------------*/
DBMS_LOB.CREATETEMPORARY( blob1, false );
dst := 1;
src := 1;
amt := 5;
DBMS_LOB.CONVERTTOBLOB(blob1, clob2, amt, dst, src, DBMS_LOB.DEFAULT_CSID,
lang, warn);
DBMS_OUTPUT.PUT_LINE(' Source offset returned ' || src ) ;
DBMS_OUTPUT.PUT_LINE(' Destination offset returned ' || dst ) ;
DBMS_OUTPUT.PUT_LINE(' Length of CLOB ' || dbms_lob.getlength(clob2) ) ;
DBMS_OUTPUT.PUT_LINE(' Length of BLOB ' || dbms_lob.getlength(blob1) ) ;
DBMS_OUTPUT.PUT_LINE(' Warning returned ' || warn);
DBMS_OUTPUT.PUT_LINE(' OUTPUT BLOB contents = ' || rawtohex(blob1));
/*------------------------------------------------------------------*/
/*-------------------- Convert BLOB to a CLOB ----------------------*/
/*------------------------------------------------------------------*/
DBMS_LOB.CREATETEMPORARY( clob3, false );
dst := 1;
src := 1;
amt := 4;
DBMS_LOB.CONVERTTOCLOB(clob3, blob1, amt, dst, src, DBMS_LOB.DEFAULT_CSID,
lang, warn);
DBMS_OUTPUT.PUT_LINE(' Source offset returned ' || src ) ;
DBMS_OUTPUT.PUT_LINE(' Destination offset returned ' || dst ) ;
DBMS_OUTPUT.PUT_LINE(' Length of BLOB ' || DBMS_LOB.GETLENGTH(blob1) ) ;
DBMS_OUTPUT.PUT_LINE(' Length of CLOB ' || DBMS_LOB.GETLENGTH(clob3) ) ;
DBMS_OUTPUT.PUT_LINE(' Warning returned ' || warn);
DBMS_OUTPUT.PUT_LINE(' INPUT BLOB contents = ' || rawtohex(blob1));
DBMS_OUTPUT.PUT_LINE(' OUTPUT CLOB contents = ' || clob3);
/*------------------------------------------------------------------*/
/*----------------------- Close ------------------------------------*/
/*------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('------------- CLOSE ---------------');
DBMS_LOB.CLOSE(clob2);
if (DBMS_LOB.ISOPEN(clob1) = 1) then
DBMS_LOB.CLOSE(clob1);
END if;
COMMIT;
END;
/
Example 8-2 PL/SQL APIs for SecureFile specific operations
conn pm/pm
-- alter the table to make lob storage as securefile
-- assume tablespace tbs_1 is ASSM
alter table print_media move
lob(ad_composite) store as securefile (deduplicate compress tablespace tbs_1)
lob(ad_sourcetext) store as securefile (compress tablespace tbs_1)
lob(ad_finaltext) store as securefile (compress tablespace tbs_1)
lob(ad_photo) store as securefile (tablespace tbs_1);
SET SERVEROUTPUT ON
DECLARE
clob1 CLOB;
blob1 BLOB;
result BINARY_INTEGER;
/* --- variables for setcontenttype, getcontenttype ----*/
get_media_type VARCHAR2(128);
set_media_type VARCHAR2(128);
/* --- variables for delta operations --------*/
amount INTEGER;
offset INTEGER;
buffer VARCHAR2(30);
readbuf VARCHAR2(50);
read_amt INTEGER;
src_offset INTEGER;
dest_offset INTEGER;
amount_old INTEGER;
BEGIN
-- fetch clob, blob values
SELECT ad_sourcetext, ad_composite
INTO clob1, blob1
FROM print_media
WHERE product_id = 2056 FOR UPDATE;
/*------------------------------------------------------------------*/
/*---------------------- Get Options -------------------------------*/
/*------------------------------------------------------------------*/
-- check whether compress option is enabled
result := DBMS_LOB.GETOPTIONS(clob1, DBMS_LOB.OPT_COMPRESS);
DBMS_OUTPUT.PUT_LINE('Get compress option on ad_sourcetext: '||result);
-- check whether compress + deduplicate is enabled
result := DBMS_LOB.GETOPTIONS(blob1, DBMS_LOB.OPT_DEDUPLICATE +
DBMS_LOB.OPT_COMPRESS);
DBMS_OUTPUT.PUT_LINE('Get compress + deduplicate option on ad_composite: '||result);
/*------------------------------------------------------------------*/
/*---------------------- Set Options -------------------------------*/
/*------------------------------------------------------------------*/
-- turn off compression
DBMS_LOB.SETOPTIONS(clob1, DBMS_LOB.OPT_COMPRESS, DBMS_LOB.COMPRESS_OFF);
-- getoptions should be 0 now
result := DBMS_LOB.GETOPTIONS(clob1, DBMS_LOB.OPT_COMPRESS);
DBMS_OUTPUT.PUT_LINE('Compress option on clob1: '||result);
-- turn off deduplication
DBMS_LOB.SETOPTIONS(blob1, DBMS_LOB.OPT_DEDUPLICATE, DBMS_LOB.DEDUPLICATE_OFF);
-- getoptions should be 0 now
result := DBMS_LOB.GETOPTIONS(blob1, DBMS_LOB.OPT_DEDUPLICATE);
DBMS_OUTPUT.PUT_LINE('Deduplicate option on blob1: '||result);
/*------------------------------------------------------------------*/
/*----------- Getcontenttype, Setcontenttype -----------------------*/
/*------------------------------------------------------------------*/
-- get contenttype -- should be null as content type is not set yet
DBMS_OUTPUT.PUT_LINE(CHR(10)||'clob1 contenttype: ' || dbms_lob.getcontenttype(clob1));
set_media_type := 'text/plain';
DBMS_LOB.SETCONTENTTYPE(clob1, set_media_type);
DBMS_OUTPUT.PUT_LINE('Clob1 contenttype: ' || dbms_lob.getcontenttype(clob1));
-- setcontenttype for blob
DBMS_OUTPUT.PUT_LINE('blob1 contenttype: ' || dbms_lob.getcontenttype(blob1));
set_media_type := 'photo/jpeg';
DBMS_LOB.SETCONTENTTYPE(blob1, set_media_type);
get_media_type := DBMS_LOB.GETCONTENTTYPE(blob1);
DBMS_OUTPUT.PUT_LINE('Blob1 contenttype: ' || get_media_type);
/*------------------------------------------------------------------*/
/*---------------------- Fragment Operations -----------------------*/
/*------------------ Print Before Fragment Operations --------------*/
read_amt := 40;
DBMS_LOB.READ(clob1, read_amt, 1, readbuf);
DBMS_OUTPUT.PUT_LINE(CHR(10)||'Clob1 before fragment insert: '|| readbuf);
DBMS_OUTPUT.PUT_LINE(CHR(10)||'Length of clob1 before fragment operations: '|| dbms_lob.getlength(clob1));
/*--------------------- Fragment Delete ----------------------------*/
amount := 100;
offset := 10;
DBMS_LOB.FRAGMENT_DELETE(clob1, amount, offset);
/*--------------------- Fragment Insert ----------------------------*/
amount := 29;
offset := 1;
buffer := '#Verify lob Delta operations#';
DBMS_LOB.FRAGMENT_INSERT(clob1, amount, offset, buffer);
/*---------------------- Fragment Move -----------------------------*/
amount := 29;
src_offset := 100;
dest_offset := 1;
-- fragment move
DBMS_LOB.FRAGMENT_MOVE(clob1, amount, src_offset, dest_offset);
/*---------------------- Fragment Replace --------------------------*/
amount := 25;
amount_old := 29;
offset := 100;
buffer := '$Verify fragment replace$';
DBMS_LOB.FRAGMENT_REPLACE(clob1, amount_old, amount, offset,buffer);
COMMIT;
/*------------------ Verify After Fragment Operations --------------*/
read_amt := 40;
DBMS_LOB.READ(clob1, read_amt, 1, readbuf);
DBMS_OUTPUT.PUT_LINE(CHR(10)||'Clob1 after delta insert: '|| readbuf);
DBMS_OUTPUT.PUT_LINE(CHR(10)||'Length of clob1 after fragment operations: '|| dbms_lob.getlength(clob1));
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(sqlerrm);
END;
/