NULL Either amount, offset_1oroffset_2,is less than 1, or amount, offset_1, or offset_2is greater thanLOBMAXSIZE. 8.3.2.1.1 Exceptions The COMPARE function may raise the following exceptions: NOEXIST_DIRECTORY For BFILEs. UNOPENED_FILE For BFILEs. Files must be open before comparison. NOPRIV_DIRECTORY For BFILEs. INVALID_DIRECTORY For BFILEs. INVALID_OPERATION For BFILEs. 8.3.2.1.2 Restrictions The program asserts a purity level with the RESTRICT_REFERENCES pragma. PRAGMA RESTRICT_REFERENCES (compare, WNDS, RNDS, WNPS, RNPS); 8.3.2.1.3 Examples The following example compares two BFILE locators that are pointing to the same file. Note that for BFILEs we must provide a number of bytes (in the amount parameter) to compare, which is determined via the GETLENGTH function. Note also that for BFILES we must first open the files. DECLARE v_file_loc_1 BFILE; v_file_1_length INTEGER; v_file_loc_2 BFILE; BEGIN v_file_loc_1 := BFILENAME ('IMAGES', 'ourlogo.bmp'); v_file_loc_2 := BFILENAME ('IMAGES', 'ourlogo.bmp'); DBMS_LOB.FILEOPEN(v_file_loc_1); DBMS_LOB.FILEOPEN(v_file_loc_2); v_file_1_length := DBMS_LOB.GETLENGTH( v_file_loc_1); IF DBMS_LOB.COMPARE ( v_file_loc_1, v_file_loc_2, v_file_1_length) = 0 THEN DBMS_OUTPUT.PUT_LINE('file_loc_1 equals file_loc_2'); ELSE DBMS_OUTPUT.PUT_LINE('file_loc_1 is not equal to file_loc_2'); END IF; DBMS_LOB.FILECLOSEALL; END; / [Appendix A] What's on the Companion Disk? 8.3.2 Reading and Examining LOBs 416 This is the output of the script: file_loc_1 equals file_loc_2 This example compares two diagrams from the my_book_diagrams table: DECLARE CURSOR diagram_cur (num IN INTEGER) IS SELECT diagram FROM my_book_diagrams WHERE chapter_descr = 'Chapter 1' AND diagram_no = num; v_diagram_1_loc BLOB; v_diagram_2_loc BLOB; BEGIN OPEN diagram_cur (1); FETCH diagram_cur INTO v_diagram_1_loc; CLOSE diagram_cur; OPEN diagram_cur (2); FETCH diagram_cur INTO v_diagram_1_loc; CLOSE diagram_cur; IF DBMS_LOB.COMPARE (v_diagram_1_loc, v_diagram_2_loc) = 0 THEN DBMS_OUTPUT.PUT_LINE ('diagrams are equal'); ELSE DBMS_OUTPUT.PUT_LINE ('diagrams are different'); END IF; END; / This is the output of the script: diagrams are different 8.3.2.2 The DBMS_LOB.GETLENGTH function The GETLENGTH function returns the length of the input LOB. The length is in bytes for BFILEs and BLOBs, and in characters for CLOBs and NCLOBs. The headers for this program, for each corresponding LOB type, are the following: FUNCTION DBMS_LOB.GETLENGTH (lob_loc IN BLOB) RETURN INTEGER; FUNCTION DBMS_LOB.GETLENGTH (lob_loc IN CLOB CHARACTER SET ANY_CS) RETURN INTEGER; FUNCTION DBMS_LOB.GETLENGTH (lob_loc IN BFILE) RETURN INTEGER; The lob_loc parameter is the locator of the LOB whose length is to be determined. The overloaded specification allows GETLENGTH to be used with all types of LOBs. The clause ANY_CS in the specification allows either CLOB or NCLOB locators as input. The function returns the length (in bytes or characters) of the input LOB, or it returns NULL if the input LOB is NULL or invalid. [Appendix A] What's on the Companion Disk? 8.3.2 Reading and Examining LOBs 417 8.3.2.2.1 Restrictions The program asserts a purity level with the RESTRICT_REFERENCES pragma. PRAGMA RESTRICT_REFERENCES (getlength, WNDS, RNDS, WNPS, RNPS); 8.3.2.2.2 Examples The following example gets the size in bytes of the file ch01_01.bmp in the IMAGES directory: DECLARE v_file_loc BFILE; v_diagram_size INTEGER; BEGIN v_file_loc := BFILENAME('IMAGES','ch01_01.bmp'); v_diagram_size := DBMS_LOB.GETLENGTH(v_file_loc); DBMS_OUTPUT.PUT_LINE('Diagram size: ' || v_diagram_size); END; / This is the output of the script: Diagram size: 481078 This example gets the size in characters of "Chapter 1" from the my_book_text table: DECLARE v_text_loc CLOB; BEGIN v_text_loc := book_text ('Chapter 1'); DBMS_OUTPUT.PUT_LINE ('Length of Chapter 1: ' || DBMS_LOB.GETLENGTH(v_text_loc)); END; / This is the output of the script: Length of Chapter 1: 100 8.3.2.3 The DBMS_LOB.READ procedure The READ procedure provides piece−wise read access to a LOB. A specified number of bytes (BFILE, BLOB) or characters (CLOB, NCLOB) is read into the buffer, starting from a specified location. The number of bytes or characters actually read by the operation is returned. The headers for this program, corresponding to each type, are the following: PROCEDURE DBMS_LOB.READ (lob_loc IN BLOB | BFILE, amount IN OUT BINARY_INTEGER, offset IN INTEGER, buffer OUT RAW); PROCEDURE DBMS_LOB.READ (lob_loc IN CLOB CHARACTER SET ANY_CS, amount IN OUT BINARY_INTEGER, offset IN INTEGER, buffer OUT VARCHAR2 CHARACTER SET lob_loc%CHARSET); The overloaded specification allows READ to be used with all types of LOBs. The term ANY_CS in the [Appendix A] What's on the Companion Disk? 8.3.2 Reading and Examining LOBs 418 specification allows either CLOB or NCLOB locators as input. The READ procedure and the DBMS_LOB.SUBSTR function provide similar functionality. READ is a procedure, while SUBSTR is a function. However, READ will raise NO_DATA_FOUND and INVALID_ARGVAL exceptions, while SUBSTR will ignore these exceptions and return NULL when they occur. DBMS_LOB.SUBSTR can also be called from within a SQL statement, but READ cannot be, since it is a procedure. Parameters are summarized in the following table. Parameter Description lob_loc A locator for the LOB to be read amount Number of bytes (BFILE, BLOB) or characters (CLOB, NCLOB) to read; the number of bytes or characters actually read by the operation is returned in amount offset Location of the byte (BFILE, BLOB) or character (CLOB, NCLOB) in the LOB at which the read begins buffer Buffer where the results of the read operation are placed 8.3.2.3.1 Exceptions The READ procedure may raise any of the following exceptions: VALUE_ERROR lob_loc, amount, or offset is NULL. INVALID_ARGVAL One of the following conditions exists: • amount< 1 or amount> 32767 • offset< 1 or offset> LOBMAXSIZE • size of amount> size of buffer NO_DATA_FOUND The end of the LOB is reached. UNOPENED_FILE For BFILEs, files must be open before the read. NOEXIST_DIRECTORY For BFILEs. NOPRIV_DIRECTORY For BFILEs. INVALID_DIRECTORY For BFILEs. INVALID_OPERATION [Appendix A] What's on the Companion Disk? 8.3.2 Reading and Examining LOBs 419 For BFILEs. 8.3.2.3.2 Examples The following example reads the first 60 characters of the CLOB chapter_text column of the my_book_texttable using the "Chapter 1" row: DECLARE v_text_loc CLOB; v_text_amt BINARY_INTEGER := 60; v_text_buffer VARCHAR2(60); BEGIN v_text_loc := book_text ('Chapter 1'); DBMS_LOB.READ (v_text_loc, v_text_amt, 1, v_text_buffer); DBMS_OUTPUT.PUT_LINE('Chapter 1: ' || v_text_buffer); END; / This is the output of the script: Chapter 1: It was a dark and stormy night. Suddenly a scream rang out. The next example reads sixty characters at a time from the CLOB chapter_text column of the my_book_text table using the "Chapter 1" row. Note that the loop continues until READ raises the NO_DATA_FOUND exception. DECLARE v_text_loc CLOB; v_text_amt BINARY_INTEGER := 60; v_text_pos INTEGER := 1; v_text_buffer VARCHAR2(60); BEGIN v_text_loc := book_text ('Chapter 1'); LOOP DBMS_LOB.READ (v_text_loc, v_text_amt, v_text_pos, v_text_buffer); /* process the text and prepare to read again */ DBMS_OUTPUT.PUT_LINE('Chapter 1: ' || v_text_buffer); v_text_pos := v_text_pos + v_text_amt; END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('End of Chapter Reached.'); END; / This script produces the following: Chapter 1: It was a dark and stormy night. Suddenly a scream rang out. Chapter 1: An EXCEPTION had not been handled. End of Chapter Reached. Note that the maximum size of a VARCHAR2 or RAW variable is 32767 bytes. This is the size limit of the buffer to be used with READ. 8.3.2.4 The DBMS_LOB.SUBSTR function The SUBSTR function provides piece−wise access to a LOB. The specified number of bytes (BFILE, BLOB) or characters (CLOB, NCLOB) is returned, starting from the specified location. The headers for this program, corresponding to each LOB type, are the following: [Appendix A] What's on the Companion Disk? 8.3.2 Reading and Examining LOBs 420