NO_DATA_FOUND Not Raised

Why NO_DATA_FOUND Behavior Differs in SQL and PL/SQL

Many Oracle developers including myself for years, assume that when a PL/SQL function contains a SELECT INTO statement that returns no rows, it will raise a NO_DATA_FOUND exception. While this is true in a PL/SQL context, the behavior is different when the same function is called from SQL: the exception is silently suppressed, and the function simply returns NULL. This subtle difference can introduce unexpected logic bugs if you’re not aware of it. In this post, we’ll dive into this behavior, explain why it happens, and how to handle it properly.

NO_DATA_FOUND actually is not an error – it’s an exceptional condition. In SQL, when no rows match, in PL/SQL however, the same NO_DATA_FOUND signal is treated differently. Since PL/SQL expects a row to be returned in a SELECT INTO, the absence of data raises an exception. If not explicitly handled, it results in an error message and program interruption

So technically, both SQL and PL/SQL raise the same signal. But the client environment (SQL engine vs. PL/SQL runtime) interprets it differently. SQL assumes it’s normal. PL/SQL assumes it’s a problem unless the programmer says otherwise.

This behavior also explained by Tom Kyte in ASKTOM – NO_DATA_FOUND in Functions

Let’s create a table and a PL/SQL function.

Testing from PL/SQL (Exception Raised) :

Testing from SQL (No Exception Raised) : Null Value Returned

Oracle SQL has no mechanism for propagating PL/SQL exceptions like NO_DATA_FOUND and back to the SQL layer. Instead, the function execution returns NULL. This is by design.

NO_DATA_FOUND Not Raised
NO_DATA_FOUND Not Raised in SQL

Here is the table of PL/SQL Predefined Exceptions from Database PL/SQL Language Reference Release 19:

The only positive error code is for NO_DATA_FOUND.

Exception NameError Code
ACCESS_INTO_NULL-6530
CASE_NOT_FOUND-6592
COLLECTION_IS_NULL-6531
CURSOR_ALREADY_OPEN-6511
DUP_VAL_ON_INDEX-1
INVALID_CURSOR-1001
INVALID_NUMBER-1722
LOGIN_DENIED-1017
NO_DATA_FOUND+100
NO_DATA_NEEDED-6548
NOT_LOGGED_ON-1012
PROGRAM_ERROR-6501
ROWTYPE_MISMATCH-6504
SELF_IS_NULL-30625
STORAGE_ERROR-6500
SUBSCRIPT_BEYOND_COUNT-6533
SUBSCRIPT_OUTSIDE_LIMIT-6532
SYS_INVALID_ROWID-1410
TIMEOUT_ON_RESOURCE-51
TOO_MANY_ROWS-1422
VALUE_ERROR-6502
ZERO_DIVIDE-1476

Oracle’s +100 return code for “no data found” aligns with the behavior described in the ANSI SQL/92 (ISO/IEC 9075-2:1992 Part 2: Embedded SQL) standard for embedded SQL. Although SQLCODE itself is not officially part of the ANSI standard, starting with SQL-92, SQLSTATE became mandatory, and SQLCODE was effectively deprecated in the context of standardized SQL. However, the +100 convention for “no data” is standardized and has been widely adopted by multiple database systems such as DB2, Informix, and others that implement embedded SQL in languages like C or COBOL.

The difference in behavior between SQL and PL/SQL when handling NO_DATA_FOUND in functions is subtle but critical. If you assume the exception will propagate in all contexts, you risk introducing silent logic errors into your applications. Understanding this behavior can save you hours of debugging and help you write more robust, predictable code.

Hope it helps. See you on the next post – Part 4 : Aggregate Function Behaviors with No Matching Rows: GROUP BY vs. No GROUP BY


Discover More from Osman DİNÇ


Comments

Leave your comment