Name

BIP-05: Encapsulate UTL_FILE.GET_LINE to avoid propagating the NO_DATA_FOUND exception.

Synopsis

UTL_FILE.GET_LINE raises the NO_DATA_FOUND exception when it reads past the end of a file (a common and even necessary “error” when you are reading the full contents of a file).

This reliance on an exception to signal EOF results in poorly structured code. Consider the following:

BEGIN
   LOOP
      UTL_FILE.GET_LINE (file_id, l_line);
      process_line (l_line);
   END LOOP;

   ... lots of code
EXCEPTION
   WHEN NO_DATA_FOUND
   THEN
      UTL_FILE.FCLOSE (file_id);
END;

The problem with this code is that the simple loop looks, for all intents and purpose, like an infinite loop. It’s impossible to tell by looking at the code what makes the loop terminate. Upon termination, be sure to close the file. This logic is implemented in the exception section, which may be far away from the loop. This physical separation of logically related code can lead to a maintenance nightmare.

Instead of using UTL_FILE.GET_LINE directly, build your own “get next line” procedure and have it return a Boolean flag indicating whether the EOF was reached.

Example

Here’s a simple substitution for UTL_FILE.GET_LINE:

CREATE OR REPLACE PROCEDURE get_next_line (
   file_in    IN       UTL_FILE.file_type,
   line_out   OUT      VARCHAR2,
   eof_out    OUT      BOOLEAN
)
IS
BEGIN
   UTL_FILE.GET_LINE (file_in, line_out);
   eof_out := FALSE;
EXCEPTION
   WHEN NO_DATA_FOUND
   THEN
      line_out := NULL;
      eof_out := TRUE;
END;

Using this program, the earlier block of code becomes:

BEGIN LOOP get_next_line ...

Get Oracle PL/SQL Best Practices now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.