Handling REF CURSOR Returned by Stored Procedures in PL/SQL: A Complete Guide from Retrieval to Output

Dec 06, 2025 · Programming · 11 views · 7.8

Keywords: PL/SQL | REF CURSOR | Stored Procedure

Abstract: This article delves into the techniques for processing REF CURSOR returned by stored procedures in Oracle PL/SQL environments. It begins by explaining the fundamental concepts of REF CURSOR and its applications in stored procedures, then details two primary methods: using record types to loop through and output data, and leveraging SQL*Plus bind variables for simplified output. Through refactored code examples and step-by-step analysis, the article provides technical implementations from defining record types to complete result output, while discussing the applicability and considerations of different approaches to help developers efficiently handle dynamic query results.

Basic Concepts and Applications of REF CURSOR

In Oracle PL/SQL programming, REF CURSOR is a dynamic cursor type that allows stored procedures or functions to return query result sets without predefining specific column structures. This mechanism is particularly useful for scenarios requiring dynamic SQL queries based on runtime conditions. For example, when a stored procedure needs to return complex or variable query results, using REF CURSOR as an OUT parameter enables flexible data transfer to callers.

Processing REF CURSOR with Record Types

To retrieve and output data from a REF CURSOR, it is essential to define a record type that matches the column structure of the query result. Record types allow handling multiple columns as a single entity, simplifying data manipulation. Below is a refactored code example demonstrating how to define a record type, call a stored procedure to obtain a REF CURSOR, and loop through the results for output:

DECLARE
  TYPE grant_rec IS RECORD (
    grant_id VARCHAR2(50),
    grant_name VARCHAR2(200),
    amount NUMBER
  );
  rec grant_rec;
  ref_cursor SYS_REFCURSOR;
BEGIN
  PMAWEB_PKG.GetGrantListByPI('Smith', 'John', 'last_name', ref_cursor);
  
  LOOP
    FETCH ref_cursor INTO rec;
    EXIT WHEN ref_cursor%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Grant ID: ' || rec.grant_id || ', Name: ' || rec.grant_name || ', Amount: ' || rec.amount);
  END LOOP;
  CLOSE ref_cursor;
END;

In this example, we first define the grant_rec record type with three fields: grant_id, grant_name, and amount. Then, the stored procedure GetGrantListByPI is called to obtain the REF CURSOR, and a loop is used to fetch each row into the record variable. After each fetch, data is output to STDOUT via DBMS_OUTPUT.PUT_LINE. Note that the loop condition ref_cursor%NOTFOUND checks if all rows have been fetched, preventing infinite loops.

SQL*Plus Bind Variable Method

Beyond handling REF CURSOR within PL/SQL blocks, SQL*Plus bind variables can simplify output. This approach is suitable for quick result viewing but offers limited formatting control. Below is an example using bind variables:

VAR x REFCURSOR
EXEC PMAWEB_PKG.GetGrantListByPI('Smith', 'John', 'last_name', :x)
PRINT x

In this example, VAR x REFCURSOR declares a bind variable x as a REF CURSOR type. Then, the EXEC command executes the stored procedure and assigns the result to :x. Finally, the PRINT x command automatically outputs all rows to STDOUT. This method eliminates the need for loops or record type definitions, but the output format is determined by SQL*Plus defaults, which may not suit complex data presentation needs.

Technical Details and Best Practices

When handling REF CURSOR, several key points must be considered. First, ensure that the fields of the record type exactly match the column order and data types of the query result to avoid runtime errors. Second, use the %NOTFOUND attribute as the loop exit condition to prevent missing data or infinite loops. Additionally, when outputting data, consider using delimiters or formatted strings for better readability, such as concatenating fields in DBMS_OUTPUT.PUT_LINE.

From a performance perspective, the record type method offers greater flexibility and control, making it suitable for scenarios requiring further data processing, while the bind variable method is better for quick debugging or simple output. In practice, it is advisable to choose the appropriate method based on specific requirements, such as using record types in automated scripts and bind variables in interactive queries.

Conclusion and Extended Considerations

This article has presented two methods for processing REF CURSOR returned by stored procedures: loop-based output using record types and SQL*Plus bind variable output. The record type method, by defining structured variables, allows fine-grained control over data retrieval and output, ideal for complex data handling; whereas the bind variable method simplifies operations, suitable for quick result inspection. Developers should select the appropriate technique based on application contexts, paying attention to details like data type matching and loop control to ensure code robustness and efficiency.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.