This action might not be possible to undo. Are you sure you want to continue?
I/O in PL/SQL: Managing Files Displaying Output to Screen Sending Email
PL/SQL Evangelist, Quest Software
email@example.com PL/SQL Obsession - www.ToadWorld.com/SF
Copyright 2000-2010 Steven Feuerstein - Page 1
How to benefit most from this session
Watch, listen, focus on concepts and principles. Download and use any of my training materials:
Download and use any of my scripts (examples, performance scripts, reusable code) from the same location: the demo.zip file.
You have my permission to use all these materials to do internal trainings and build your own applications. – But remember: they are not production ready. – You must test them and modify them to fit your needs.
Copyright 2000-2008 Steven Feuerstein - Page 2
And there's more!
Copyright 2000-2008 Steven Feuerstein - Page 3
I/O in PL/SQL
You don't always read information from and write data to a relational table. Sometimes you need to read/write files. Sometimes you need to display information to the screen (system output). Sometimes you need to send emails. Sometimes....you need to take advantage of those built-in (supplied) packages.
Copyright 2000-2010 Steven Feuerstein - Page 4
I/O in PL/SQL – Relevant Oracle Technologies UTL_FILE – read and write OS files DBMS_LOB – manipulate BFILEs External tables DBMS_OUTPUT – send text to the screen UTL_MAIL – send emails Use external procedures (C code) and Java stored procedures for OS activities. Copyright 2000-2010 Steven Feuerstein . – I will touch on Java extensions to UTL_FILE.Page 5 .
it was a fairly primitive utility. Prior to Oracle9i Release 2. rename files.>> File IO in PL/SQL UTL_FILE allows you to read from and write to operating system files on the database server. but 9. – Remove.Page 6 . – Work with database directories. copy.2 offered many enhancements. Hurray! Copyright 2000-2007 Steven Feuerstein .
Copyright 2000-2010 Steven Feuerstein . – Most of exceptions raised are non-specific and minimally useful. as in "Invalid file operation. – Documents exceptions for each subprogram. – Ask your DBA for read-only access.UTL_FILE Logistics $ORACLE_HOME/Rdbms/Admin The UTL_FILE package is defined in the utlfile.sql file of the RDBMS/Admin directory.Page 7 ." UTL_FILE is not installed in Oracle XE. Includes a long list of file-specific exceptions.
Enabling UTL_FILE Access While UTL_FILE is available by default to all schemas connected to Oracle. among other things! So a user with DBA authority must authorize access to specific directories. Copyright 2000-2010 Steven Feuerstein . Oracle is very cautious.Page 8 . also by default you have no ability to actually read/write files. – They don't want you to accidentally delete Oracle database files.
Page 9 .Authorizing Directory Access – UTL_FILE_DIR In the bad old days of UTL_FILE. the only way to enable a directory for read/write was the UTL_FILE_DIR parameter. Not well suited for the 24x7 world of the 21st century. Very awkward and inflexible. – And after you change it. utl_file_dir = /tmp utl_file_dir = /accounts/newdev Copyright 2000-2007 Steven Feuerstein . you have to "bounce" the database before UTL_FILE will recognize the directory.
GRANT CREATE ANY DIRECTORY TO <schema_name> Copyright 2000-2007 Steven Feuerstein . – Once created. – It is generally a DBA-only action. Directory names are case-sensitive. Special privilege needed to create directory.Authorizing Directory Access – the modern way Now you can take advantage of database directory objects instead of UTL_FILE_DIR. it is available for use immediately. – A directory is a database object. define with a CREATE statement.Page 10 .
sql utlfile_92. Check the ALL_DIRECTORIES view to determine which directories you can use. directory_name. Can grant read and/or write privileges to schemas. CREATE OR REPLACE DIRECTORY ERROR_LOG AS '/tmp/apps/log'. create_directories.Page 11 .sql Copyright 2000-2007 Steven Feuerstein . directory_path FROM ALL_DIRECTORIES. hard-coded location. SELECT owner.Working with Database Directories The directory hides the actual. GRANT READ ON DIRECTORY error_log TO SCOTT.
END.fclose (fid).Opening a File DECLARE fid UTL_FILE. operation type and (optionally) the maximum line size. – Contains three fields (ID. – Types are 'R' for Read. Up to 50 files open per session.txt'.Page 12 fopen_write_conflict. BEGIN fid := UTL_FILE. name. fopen. 'W'.sql . – Linesize default is 1024.sql Copyright 2000-2007 Steven Feuerstein . max_linesize => 32767). 'W' for Write and 'A' for Append. UTL_FILE. maximum of 32767 The FOPEN function returns a record ("file handle") based on the UTL_FILE.FOPEN ('TEMP_DIR'.FILE_TYPE. 'test. Specify file location. datatype and byte_mode).FILE_TYPE.
fopen ('TEMP'. 'test. max_linesize => 32767). – Not much of a test. this function simply returns TRUE if the file handle's id field is NOT NULL.. Test to see if file is open with the IS_OPEN function.put_line ('File is open'). IF UTL_FILE.put_line ('File is closed').txt'. – In actuality. END IF. Copyright 2000-2007 Steven Feuerstein ..Page 13 .Is a File Open? DECLARE fid UTL_FILE. BEGIN fid := UTL_FILE. 'W'. END.is_open (fid) THEN DBMS_OUTPUT. ELSE DBMS_OUTPUT.fclose (fid).file_type. UTL_FILE.
sql infile. 'R'). Can only read one line at a time. END. UTL_FILE.FCLOSE (fid).GET_LINE (fid.FOPEN ('TEMP'.Reading from a File DECLARE fid UTL_FILE. Can only read from a file opened with the "R" mode. – That's more than a little bit silly – and a bad idea.sf Copyright 2000-2007 Steven Feuerstein . 'test. The NO_DATA_FOUND exception is raised if you read past the end of the file. read_from_file.txt'.FILE_TYPE. UTL_FILE. myline). BEGIN fid := UTL_FILE.sf eqfiles.Page 14 .
Page 15 getnext.sql Copyright 2000-2010 Steven Feuerstein . It's what you do when you read the full contents of a file. – Leading to scary and hard-to-manage code.sp file_to_collection. exec_ddl_from_file.sql .A better GET_LINE function Reading past the end of a file isn't an error. But UTL_FILE's architecture requires that your block terminates and you trap the exception. So "hide" GET_LINE inside your own filereading program.
BEGIN fid := UTL_FILE. – \n is new line.PUT_LINE (fid. UTL_FILE. ' that I never\nwant to %s'. UTL_FILE. PUT puts a line without a newline terminator.FCLOSE (fid).Page 16 .PUT (fid. write_to_file. PUT_LINE = PUT plus newline character. 'test. 'stop!').sql Copyright 2000-2007 Steven Feuerstein . PUTF allows for some formatting and substitution. 'is so much fun').FILE_TYPE. %s substitutes strings.sql display_file.sql create_file.Writing to a File DECLARE fid UTL_FILE. UTL_FILE. 'W').FOPEN ('TEMP'. UTL_FILE. END.sp read_and_write.txt'. 'UTL_FILE').PUTF (fid.sql genaa.
it most likely is not.Flushing content to file A call to PUT_LINE does not necessarily mean the text is in the file.tst Copyright 2000-2010 Steven Feuerstein . You can specify each new line flushed out in call to PUT_LINE. put_line_performance.FFLUSH to write the accumulated buffer contents out to the file. – In fact. – Writing out to the actual file is performed asynchronously.Page 17 . Or call UTL_FILE.
myline).Closing a File DECLARE fid UTL_FILE. UTL_FILE. – And also close them when an exception is raised. UTL_FILE. Copyright 2000-2007 Steven Feuerstein .READ_ERROR THEN UTL_FILE. EXCEPTION WHEN UTL_FILE. Close all open files in session with FCLOSE_ALL. 'test. Very important to close files when you are done with them. Otherwise the file is left open and data will not be flushed out to disk. END.Page 18 . BEGIN fid := UTL_FILE. 'R').txt'.FCLOSE (fid).FOPEN ('TEMP'.GET_LINE (fid.FILE_TYPE.FCLOSE (fid).
Page 19 .High Level Functionality of UTL_FILE Copy a file with FCOPY Delete a file with FREMOVE Rename and move a file with FRENAME Find current position in file with FGETPOS Retrieve characteristics of file with FGETATTR Copyright 2000-2010 Steven Feuerstein .
sql backup_with_fcopy. or a specify range of lines by start and end line numbers. Copy all lines in the file..fcopy ( src_location => 'DEVELOPMENT_DIR'.zip'.pkg . END. dest_location => 'ARCHIVE_DIR'.Copy a File DECLARE file_suffix VARCHAR2 (100) := TO_CHAR (SYSDATE.zip' ). Copyright 2000-2007 Steven Feuerstein . src_filename => 'archive.Page 20 fcopy. BEGIN UTL_FILE. dest_filename => 'archive' || file_suffix || '.sql fileIO92. 'YYYYMMDDHH24MISS'). You don't open/close the file.
src_filename => 'archive. then you deleted successfully fremove.delete_failed THEN .sql fileIO92.Page 21 .pkg Copyright 2000-2007 Steven Feuerstein .. EXCEPTION /* Don't forget to check for errors! */ WHEN UTL_FILE.zip' ). If no error is raised..fremove ( src_location => 'DEVELOPMENT_DIR'. Deal with failure to remove END.Remove a File BEGIN UTL_FILE.
pkg Copyright 2000-2007 Steven Feuerstein .frename ( src_location => 'DEVELOPMENT_DIR'. If you rename with a new directory. 'YYYYMMDD'). BEGIN -. frename. dest_location => 'ARCHIVE_DIR'.zip'.Rename/move a File DECLARE file_suffix VARCHAR2 (100) := TO_CHAR (SYSDATE. UTL_FILE.Page 22 .Rename/move the entire file in a single step. overwrite => FALSE ). you will move the file. src_filename => 'archive. dest_filename => 'archive' || file_suffix || '.END.sql fileIO92. Use FRENAME to change the name of a file.zip'.
file_type. in bytes. END LOOP. Use the FGETPOS function to get the current relative offset position within a file. 'R'.get_line (fid.fclose (fid). BEGIN fid := UTL_FILE. l_line VARCHAR2 (32767). 'temp.fopen ('TEMP'. max_linesize => 32767).put_line (UTL_FILE. UTL_FILE. DBMS_OUTPUT.Page 23 . 10 LOOP UTL_FILE..txt'. Returns 0 when you are writing to a file.fgetpos (fid)). fgetpos.Find current position in file DECLARE fid UTL_FILE. END. FOR indx IN 1 . l_line).sql Copyright 2000-2010 Steven Feuerstein .
fgetattr ( location => location_in. block_size => fgetattr_rec.block_size ). block_size PLS_INTEGER ). RETURN fgetattr_rec. All answered with a call to UTL_FILE. fexists => fgetattr_rec.Page 24 .sql fileIO92.FGETATTR.file_length. file_length => fgetattr_rec. END flength. file_length PLS_INTEGER. fgetattr_rec fgetattr_t.fexists. BEGIN UTL_FILE.pkg Copyright 2000-2007 Steven Feuerstein .file_length. flength.Obtaining attributes of a file CREATE OR REPLACE FUNCTION flength ( location_in IN VARCHAR2. filename => file_in. file_in IN VARCHAR2 ) RETURN PLS_INTEGER IS TYPE fgetattr_t IS RECORD ( fexists BOOLEAN. How big is a file? What is its block size? Does the file exist? All valuable questions.
files in directory. – No higher-level file operations (change privileges.Extending file operations with Java There are still lots of restrictions in UTL_FILE. random access to contents).pkg Copyright 2000-2010 Steven Feuerstein . you could consider a switch to Java. – Limitations on files you can access (no mapped files.Page 25 . no use of environmental variables). – But you need the DBA to grant you the Java privileges to interact with the OS. JFile.java xfile. If you hit these limits. create directory.
External Tables – query from files! External tables are defined as schema objects. Specify structure of file using SQL Loader control file syntax.Page 26 . Query the contents of the file using standard SQL syntax. but the data is stored in a file. Copyright 2000-2010 Steven Feuerstein .
dname VARCHAR2(20).* ..External Tables – simple example File contains department information: 1.Information Services.Page 27 external_tables*.Human Resources.New York My create table statement "points" to the file: CREATE TABLE departments_ext ( deptno NUMBER(6). loc VARCHAR2(25) ) . LOCATION ('departments.Chicago 2.ctl') ) Copyright 2000-2010 Steven Feuerstein ..
txt') ) Copyright 2000-2010 Steven Feuerstein .* . CREATE TABLE files_in_temp ( file_name VARCHAR2(1000) ) ORGANIZATION external ( TYPE oracle_loader DEFAULT DIRECTORY TEMP ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE PREPROCESSOR execute_directory: 'show_files.2.External Tables – 11.bat' FIELDS TERMINATED BY WHITESPACE ) LOCATION ('placeholder. Oracle extended the external table concept to include a preprocessor option. You specify an operating system file that will run when you execute a query against the external table.2 example: get files in directory In 11.Page 28 external_tables_files_in_dir.
This will not constitute a training on working with LOBs! Copyright 2000-2010 Steven Feuerstein .DBMS_LOB and BFILEs Oracle allows you to also manipulate binary files or BFILEs through the DBMS_LOB package. but they don't have to be. A BFILE is a pointer to an OS file.Page 29 . – The intention is to work with really big files.
Copyright 2000-2010 Steven Feuerstein . – Read BFILE into LOB – Perform INSTR and SUBSTR operations on a BFILE...DBMS_LOB BFILE functionality Open and close BFILEs Compare two BFILES with COMPARE. Get information about a BFILE – Name and location? exists? length? Read contents of BFILE – They are read-only structures! And more.Page 30 .
END.Open and Close BFILES DECLARE l_bfile BFILE := BFILENAME ('DEMO'. DBMS_OUTPUT. DBMS_LOB.fileisopen (l_bfile)). Then it's all as expected.fileclose (l_bfile). 'exec_ddl_from_file2.put_line ('Exists? ' || DBMS_LOB. DBMS_OUTPUT.put_line ('Open after open? ' || DBMS_LOB.sql').sql Copyright 2000-2010 Steven Feuerstein .fileopen (l_bfile).fileexists (l_bfile)). BEGIN DBMS_OUTPUT. bfile_open_close. Initialize BFILE pointer with the BFILENAME function.fileisopen (l_bfile)). DBMS_LOB.put_line ('Open before open? ' || DBMS_LOB.fileisopen (l_bfile)). DBMS_OUTPUT. put_line ('Open after close? ' || DBMS_LOB.Page 31 .
l_bfile2 BFILE := BFILENAME ('TEMP'. BEGIN DBMS_LOB. 'file2. offset_2 => 1 ) ). – Specify amount of file you want to compare. offset_1 => 1.fileopen (l_bfile2).put_line ( 'Equal? ' || DBMS_LOB. file_2 => l_bfile2 .txt').Compare two BFILES with COMPARE DECLARE l_bfile1 BFILE := BFILENAME ('TEMP'.txt'). Copyright 2000-2010 Steven Feuerstein . DBMS_LOB.fileclose (l_bfile1). amount => 33. 'file1.fileclose (l_bfile2). DBMS_OUTPUT. DBMS_LOB.sql .Page 32 bfile_compare.compare (file_1 => l_bfile1. END.fileopen (l_bfile1). Use the COMPARE program to find out if two BFILEs are the same. and the offset locations in each. DBMS_LOB.
GETLENGTH Does the file exist? FILEEXISTS Is the file open? FILEISOPEN bfile_demo.sql Copyright 2000-2010 Steven Feuerstein .Page 33 .Get information about a BFILE Get the name of the file: FILEGETNAME Get length of the file.
Copyright 2000-2010 Steven Feuerstein . 1. l_amount.sql'). You always read into a RAW variable. l_contents). l_contents RAW (32767).Read contents of BFILE DECLARE l_bfile BFILE := BFILENAME ('DEMO'. these are supposed to be binary files! The amount is IN OUT – it returns the actual number of bytes read. DBMS_LOB. l_amount PLS_INTEGER := 100.read (l_bfile. dbms_output. END.fileopen (l_bfile).fileclose (l_bfile). BEGIN DBMS_LOB. – After all. DBMS_LOB.put_line (l_contents). 'exec_ddl_from_file.Page 34 bfile_read.sql .
Historically crippled.Writing data to system output Use DBMS_OUTPUT to display information on your screen. – Often used as a cheap and easy debugging or tracing mechanism. Best known built-in package and most abused.Page 35 . – Unlimited buffer size – Display strings of up to 32767 characters. today many limitations are removed. SET SERVEROUTPUT ON SIZE UNLIMITED Copyright 2000-2010 Steven Feuerstein .
Enable and disable output Calls to DBMS_OUTPUT. This is often performed by host environments. – SET SERVEROUTPUT ON You can also enable output with a call to DBMS_OUTPUT. but it is not enough.Page 36 . – The host environment must also be ready to retrieve the contents of the buffer.ENABLE. Copyright 2000-2010 Steven Feuerstein .PUT_LINE and others will do nothing unless output is enabled.
Put information on screen All information is placed in buffer. NEW_LINE adds end-of-line marker.Page 37 . PUT_LINE puts a line of text and end-of-line marker. Copyright 2000-2010 Steven Feuerstein . which is retrieved with a call to GET_LINES. PUT puts text in buffer without end-of-line marker.
Copyright 2000-2010 Steven Feuerstein . It is very unlikely that you will ever run into a need to call the GET* procedures.Page 38 dbms_output_demo. GET_LINES returns all lines in buffer into a PL/SQL collection.Get information from the buffer GET_LINE retrieves the next line from the buffer.sql .
The demo. Copyright 2000-2010 Steven Feuerstein . Do not use this built-in for tracing or debugging.PUT_LINE in your production code.Page 39 . Encapsulate it to make it more useful and less problematic.Summary: DBMS_OUTPUT Avoid calls to DBMS_OUTPUT.zip contains numerous alternatives.
l" to say "show me". many overloadings of datatypes. The watch package – Write information to screen or database pipe Quest Error Manager – www.Alternatives to DBMS_OUTPUT The p package – Use "p.pks/pkb watch_noplv.ToadWorld.com/SF – More sophisticated tracing and error management Copyright 2000-2010 Steven Feuerstein .Page 40 p.pkg .
– Set the SMTP_OUTPUT_SERVER parameter. That's right .Page 41 ..plb files under SYS. – Install the utlmail. Copyright 2000-2007 Steven Feuerstein .Sending mail from a PL/SQL program UTL_MAIL makes it much easier to send email from within PL/SQL by hiding some of the complexities of UTL_SMTP..it is not installed by default.sql and prvtmail. To use UTL_MAIL. – Grant EXECUTE on UTL_MAIL as desired.
send sender .cc .com' 'me@mydomain. .Send without attachment The interface to the SEND program mimics the basic "send email" form of Outlook and other email programs.Page 42 ( => => => => => => 'firstname.lastname@example.org' 'email@example.com .subject . BEGI UTL_MAIL. Copyright 2000-2007 Steven Feuerstein .message 'Hi Ya''ll. END. him@hisdomain. Bill' ).recipients . Sending email in Give it a try! Mailfully Yours.com' 'firstname.lastname@example.org' 'Cool new API for sending email' PL/SQL is *much* easier with UTL_MAIL in 10g.
email@example.com => 'me@mydomain.' /* Content of the attachment */ .att_filename => '.send_attachment_raw ( sender => 'me@mydomain.Page 43 .. */ ). END. Copyright 2000-2007 Steven Feuerstein .com' .com.' ..Send with attachment You can attach RAW or VARCHAR2 content as an attachment (up to 32K).. BEGIN UTL_MAIL.recipients => 'firstname.lastname@example.org => 'Cool new API for sending email' .att_inline => TRUE /* Attachment in-line? */ .message => '.attachment => '..' /* Name of file to hold the attachment after the mail is received.com' .cc => 'mom@momdomain...com' .com' .
Page 44 . but problematic. Copyright 2000-2010 Steven Feuerstein . UTL_FILE has improved over time. the built-in packages help by extending PL/SQL.The World is Bigger Than Relational Tables Most of our work in PL/SQL involves reading and writing the contents of tables." In these cases. Sometimes. we need to interact with the world "out there. DBMS_OUTPUT is unavoidable. but could use a lot more work. though.
This action might not be possible to undo. Are you sure you want to continue?
We've moved you to where you read on your other device.
Get the full title to continue reading from where you left off, or restart the preview.