The following anonymous block shows how you might construct an exception section that will close any open files: DECLARE book_file_loc BFILE := NULL; book_file_exists BOOLEAN := FALSE;
Trang 1WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('OTHERS Exception ' || sqlerrm );
END;
/
This is the output of the script:
closing non_existent_file.txt in NON_EXISTENT_DIRECTORY
FILECLOSE raises a VALUE_ERROR exception when passed a NULL file locator
See the FILEOPEN and FILECLOSEALL sections for other examples of FILECLOSE usage
8.3.1.6 The DBMS_LOB.FILECLOSEALL procedure
The FILECLOSEALL procedure is used to close all BFILEs that are open within a session Here's the header for this program:
PROCEDURE DBMS_LOB.FILECLOSEALL;
8.3.1.6.1 Exceptions
The FILECLOSEALL procedure raises an UNOPENED_FILE exception if no files are open
8.3.1.6.2 Examples
When an exception occurs after opening a file, it is possible that execution continues without closing the file
(i.e., a matching call to FILECLOSE is not executed due to abnormal termination of a block) In this case, the file remains open, and we run the risk of exceeding the SESSION_MAX_OPEN_FILES limit It is good practice to include a call to FILECLOSEALL within an exception handler whenever FILEOPEN is used
The following anonymous block shows how you might construct an exception section that will close any open files:
DECLARE
book_file_loc BFILE := NULL;
book_file_exists BOOLEAN := FALSE;
x NUMBER;
BEGIN
book_file_loc := BFILENAME('BOOK_TEXT','chapter01.txt');
book_file_exists := DBMS_LOB.FILEEXISTS( book_file_loc ) = 1;
IF book_file_exists
THEN
DBMS_OUTPUT.PUT_LINE ('opening chapter01.txt');
DBMS_LOB.FILEOPEN (book_file_loc);
/* Intentionally raise a ZERO_DIVIDE exception */
x := 1 / 0;
DBMS_LOB.FILECLOSE( book_file_loc );
END IF;
EXCEPTION
WHEN OTHERS
THEN
BEGIN
DBMS_OUTPUT.PUT_LINE ('Clean up using FILECLOSEALL');
DBMS_LOB.FILECLOSEALL;
EXCEPTION
WHEN DBMS_LOB.UNOPENED_FILE
THEN
DBMS_OUTPUT.PUT_LINE
Trang 2WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('OTHERS Exception ' || sqlerrm );
END;
END;
/
This is the output of the script:
opening chapter01.txt
Clean up using FILECLOSEALL
8.3.1.7 The DBMS_LOB.LOADFROMFILE procedure
The LOADFROMFILE procedure is used to load all or part of a external LOB (source BFILE) to a
destination internal LOB This is the procedure used to load binary data stored in operating system files into internal LOBs, which reside in the database The specification for this program is overloaded as follows:
PROCEDURE DBMS_LOB.LOADFROMFILE
(dest_lob IN OUT BLOB | CLOB CHARACTER SET ANY_CS,
src_lob IN BFILE,
amount IN INTEGER,
dest_offset IN INTEGER := 1,
src_offset IN INTEGER := 1);
The overloaded specification allows LOADFROMFILE to be used with BLOBs or CLOBs The clause ANY_CS in the second specification allows acceptance of either CLOB or NCLOB locators as input
Parameters are summarized in the following table
Parameter Description
dest_lob Locator for the destination internal LOB
src_lob File locator for the source external LOB
amount Number of bytes to copy from the source BFILE
dest_offset Location of the byte (BLOB) or character (CLOB, NCLOB) in the destination LOB at which the
copy operation begins; the default value is 1
src_offset Location of the byte in the source BFILE at which the load operation begins; the default value is
1
8.3.1.7.1 Exceptions
The LOADFROMFILE procedure raises a VALUE_ERROR exception if dest_lob, src_lob, or amount are NULL or invalid
An INVALID_ARGVAL exception is raised if any of the following conditions are true:
•
src_offset < 1 or src_offset > LOBMAXSIZE
•
dest_offset < 1 or dest_offset > LOBMAXSIZE
•
amount < 1 or amount > LOBMAXSIZE
Trang 3LOADFROMFILE raises the ORA−22993 exception (specified input amount is greater than actual source amount) if the end of the source BFILE is reached before the specified amount of bytes has been copied
8.3.1.7.2 Examples
The following example loads the CLOB chapter_text column of the my_book_text table with the contents of
the first 100 bytes of the file chapter01.txt in the BOOK_TEXT directory.
Note that the update of the chapter_text column occurs without the issue of an UPDATE statement
LOADFROMFILE accomplishes this via the chapter_text locator, which has been selected FOR UPDATE LOB locators and DBMS_LOB allow changes to LOB columns in Oracle tables without issuing INSERT or UPDATE statements
If you want to take this approach, you must lock the row that contains the LOB prior to modification The best
way to obtain this lock is to use the FOR UPDATE clause in the SELECT statement (in this example, this translates to calling the book_text_forupdate function):
INSERT INTO my_book_text (chapter_descr, chapter_text)
VALUES ('Chapter 1', EMPTY_CLOB());
COMMIT;
DECLARE
v_text_loc CLOB;
v_file_loc BFILE;
BEGIN
v_text_loc := book_text_forupdate ('Chapter 1');
v_file_loc := BFILENAME('BOOK_TEXT','chapter01.txt');
DBMS_LOB.LOADFROMFILE (v_text_loc, v_file_loc, 100);
COMMIT;
END;
/
SET LONG 100
COL chapter_descr FOR A15
COL chapter_text FOR A40 WORD_WRAPPED
SELECT chapter_descr, chapter_text
FROM my_book_text
WHERE chapter_descr = 'Chapter 1';
This is the output of the script:
CHAPTER_DESCR CHAPTER_TEXT
−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Chapter 1 It was a dark and stormy night.
Suddenly a scream rang out An
EXCEPTION had not been handled.
The next example also loads the CLOB chapter_text column of the my_book_text table with the contents of
the first 100 bytes of the file chapter01.txt in the BOOK_TEXT directory This time, the LOB locator is not
selected FOR UPDATE, but has been returned via the RETURNING clause
DECLARE
v_text_loc CLOB;
v_file_loc BFILE;
BEGIN
INSERT INTO my_book_text (chapter_descr, chapter_text)
VALUES ('Chapter 1', EMPTY_CLOB )
RETURNING chapter_text INTO v_text_loc;
v_file_loc := BFILENAME('BOOK_TEXT','chapter01.txt');
DBMS_LOB.LOADFROMFILE(v_text_loc, v_file_loc, 100);
Trang 4COMMIT;
END;
/
SET LONG 100
COL chapter_descr FOR A15
COL chapter_text FOR A40 WORD_WRAPPED
SELECT chapter_descr, chapter_text
FROM my_book_text
WHERE chapter_descr = 'Chapter 1';
This is the output of the script:
CHAPTER_DESCR CHAPTER_TEXT
−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Chapter 1 It was a dark and stormy night.
Suddenly a scream rang out An
EXCEPTION had not been handled.
This example loads the BLOB diagram column of the by_book_diagrams table with the contents of the file
ch01_01.bmp in the IMAGES directory The LOB locator has been returned via the RETURNING clause.
Note that the update of the diagram column occurs without the issue of an UPDATE statement
LOADFROMFILE accomplishes this via the diagram locator, which has been returned by the RETURNING clause LOB locators and DBMS_LOB allow changes to LOB columns in Oracle tables without issuing INSERT or UPDATE statements
DECLARE
v_file_loc BFILE;
v_diagram_loc BLOB;
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);
DBMS_OUTPUT.PUT_LINE('Inserting Empty Diagram Row');
INSERT INTO my_book_diagrams (chapter_descr, diagram_no, diagram)
VALUES ( 'Chapter 1', 1, EMPTY_BLOB )
RETURNING diagram INTO v_diagram_loc;
DBMS_OUTPUT.PUT_LINE('Loading Diagram From File');
DBMS_LOB.LOADFROMFILE(v_diagram_loc, v_file_loc, v_diagram_size);
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('OTHERS Exception ' || sqlerrm);
END;
/
SELECT chapter_descr,
diagram_no,
dbms_lob.getlength(diagram) diagram_size
FROM my_book_diagrams
WHERE chapter_descr = 'Chapter 1';
Trang 5This script produces the following:
Diagram size: 481078
Inserting Empty Diagram Row
Loading Diagram From File
CHAPTER_DESCR DIAGRAM_NO DIAGRAM_SIZE
−−−−−−−−−−−−−−− −−−−−−−−−− −−−−−−−−−−−−
Chapter 1 1 481078
8.3.2 Reading and Examining LOBs
The following sections describe the programs in the DBMS_LOB package that are used to read and examine LOBs
8.3.2.1 The DBMS_LOB.COMPARE function
The COMPARE function is used to compare two LOBs that are of the same type Parts of LOBs can also be compared The specification for this program takes the following forms for each LOB type that may be
compared:
FUNCTION DBMS_LOB.COMPARE
(lob_1 IN BLOB | CLOB CHARACTER SET ANY_CS,
lob_2 IN BLOB | CLOB CHARACTER SET ANY_CS,
amount IN INTEGER := 4294967295,
offset_1 IN INTEGER := 1,
offset_2 IN INTEGER := 1)
RETURN INTEGER;
FUNCTION DBMS_LOB.COMPARE
(lob_1 IN BFILE,
lob_2 IN BFILE,
amount IN INTEGER,
offset_1 IN INTEGER := 1,
offset_2 IN INTEGER := 1)
RETURN INTEGER;
The overloaded specification allows COMPARE to be used with all types of LOBs The clause ANY_CS in the specification allows either CLOB or NCLOB locators as input
Parameters are summarized in the following table
Parameter Description
lob_1 Locator for the first LOB to be compared
lob_2 Locator for the second LOB to be compared
amount Number of bytes (BFILE, BLOB) or characters (CLOB, NCLOB) to compare
offset_1 Location of the byte (BFILE, BLOB) or character (CLOB, NCLOB) in the first LOB at which the
comparison begins; the default value is 1
offset_2 Location of the byte (BFILE, BLOB) or character (CLOB, NCLOB) in the second LOB at which
the comparison begins; the default value is 1
The function returns one of the following values:
Value Description
Zero LOBs match exactly over the offsets and amountspecified
Not Zero LOBs do not match exactly over the offsets and amountspecified