1. What is a REF CURSOR?
A REF CURSOR is a cursor variable that holds a reference to a query's result set.
DECLARE
TYPE ref_cursor_type IS REF CURSOR;
v_cursor ref_cursor_type;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
-- Process result set
CLOSE v_cursor;
END;
/
2. Why is it called REF CURSOR?
"REF" means reference. A REF CURSOR variable doesn't itself contain the rows. It holds a reference to the result set produced by a query.
REF CURSOR variable
↓
Result set
↓
+-------+-------+
| Row 1 | Row 2 |
+-------+-------+
3. What is the syntax for a REF CURSOR?
Strong/basic form:
TYPE ref_cursor_type IS REF CURSOR;
v_cursor ref_cursor_type;
OPEN v_cursor FOR
SELECT ...;
4. What is a weak REF CURSOR?
A weak REF CURSOR does not specify the structure of the returned rows.
DECLARE
TYPE ref_cursor_type IS REF CURSOR;
v_cursor ref_cursor_type;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
CLOSE v_cursor;
END;
/
The cursor can point to result sets with different structures.
5. What is a strong REF CURSOR?
A strong REF CURSOR specifies the type of rows that the cursor can return.
DECLARE
TYPE emp_ref_cursor IS REF CURSOR
RETURN employees%ROWTYPE;
v_cursor emp_ref_cursor;
BEGIN
OPEN v_cursor FOR
SELECT *
FROM employees;
CLOSE v_cursor;
END;
/
Here the cursor is strongly typed to return a row matching employees%ROWTYPE.
6. Strong vs Weak REF CURSOR
| Feature | Strong REF CURSOR | Weak REF CURSOR |
|---|---|---|
| Return type specified | Yes | No |
| Structure checked | More strictly | More flexible |
| Can point to different row structures | Limited | Yes |
| Compile-time checking | Stronger | Weaker |
| Flexibility | Lower | Higher |
Easy memory trick:
Strong = Structure known
Weak = Structure not fixed
7. What is SYS_REFCURSOR?
SYS_REFCURSOR is a predefined weak REF CURSOR type provided by Oracle. You don't need to declare your own REF CURSOR type.
DECLARE
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
CLOSE v_cursor;
END;
/
8. Why is SYS_REFCURSOR popular?
Because it is simple. Instead of declaring your own REF CURSOR type, you can simply write:
v_cursor SYS_REFCURSOR;
9. How do we OPEN a REF CURSOR?
Use:
OPEN cursor_variable FOR SELECT_statement;
Example:
DECLARE
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name
FROM employees;
CLOSE v_cursor;
END;
/
Important: For a normal explicit cursor, use OPEN emp_cursor;. For a REF CURSOR, use OPEN v_cursor FOR SELECT ...;
10. Can we FETCH from a REF CURSOR?
Yes.
DECLARE
v_cursor SYS_REFCURSOR;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
v_salary employees.salary%TYPE;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
LOOP
FETCH v_cursor
INTO v_id, v_name, v_salary;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(
v_id || ' - ' ||
v_name || ' - ' ||
v_salary
);
END LOOP;
CLOSE v_cursor;
END;
/
11. Can we CLOSE a REF CURSOR?
Yes. A REF CURSOR should be closed after its result set has been processed when the current code owns the cursor lifecycle.
CLOSE v_cursor;
12. What happens if we forget to close a REF CURSOR?
The cursor remains open and can consume database resources. Therefore, after processing, CLOSE v_cursor; should normally be performed.
13. Can we OPEN a REF CURSOR for different queries?
Yes. This is one of its major advantages.
DECLARE
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name
FROM employees;
CLOSE v_cursor;
OPEN v_cursor FOR
SELECT department_id, department_name
FROM departments;
CLOSE v_cursor;
END;
/
14. Can a REF CURSOR accept parameters?
A REF CURSOR itself does not have cursor parameters in the same way a parameterized explicit cursor does. Instead, you can use PL/SQL variables in the query.
DECLARE
v_cursor SYS_REFCURSOR;
v_dept_id NUMBER := 10;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees
WHERE department_id = v_dept_id;
CLOSE v_cursor;
END;
/
15. Can we use OPEN FOR with dynamic SQL?
Yes.
DECLARE
v_cursor SYS_REFCURSOR;
v_sql VARCHAR2(1000);
BEGIN
v_sql :=
'SELECT employee_id, first_name
FROM employees
WHERE department_id = :1';
OPEN v_cursor FOR v_sql USING 10;
CLOSE v_cursor;
END;
/
Here v_sql is the dynamic SQL statement, :1 is the bind placeholder, and 10 is supplied through USING.
16. Why is REF CURSOR useful in procedures?
A procedure can return a result set to the caller using an OUT parameter.
CREATE OR REPLACE PROCEDURE get_employees (
p_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_cursor FOR
SELECT employee_id,
first_name,
salary
FROM employees;
END;
/
The procedure doesn't return individual rows one by one. It returns a cursor pointing to the result set.
17. How do we call a procedure that returns a REF CURSOR?
DECLARE
v_cursor SYS_REFCURSOR;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
v_salary employees.salary%TYPE;
BEGIN
get_employees(v_cursor);
LOOP
FETCH v_cursor
INTO v_id, v_name, v_salary;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(
v_id || ' - ' ||
v_name || ' - ' ||
v_salary
);
END LOOP;
CLOSE v_cursor;
END;
/
18. Can a function return a REF CURSOR?
Yes.
CREATE OR REPLACE FUNCTION get_employees
RETURN SYS_REFCURSOR
IS
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id,
first_name,
salary
FROM employees;
RETURN v_cursor;
END;
/
19. Can a REF CURSOR be an OUT parameter?
Yes. This is very common.
CREATE OR REPLACE PROCEDURE get_emp_data (
p_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_cursor FOR
SELECT employee_id, first_name
FROM employees;
END;
/
20. Can a REF CURSOR be passed to another procedure?
Yes.
CREATE OR REPLACE PROCEDURE process_employees (
p_cursor IN SYS_REFCURSOR
)
IS
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
BEGIN
LOOP
FETCH p_cursor INTO v_id, v_name;
EXIT WHEN p_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_id || ' - ' || v_name);
END LOOP;
END;
/
21. Can a REF CURSOR be returned to an application?
Yes. This is one of its most important uses. A PL/SQL procedure can return a cursor, and an application can fetch the rows from that cursor.
22. REF CURSOR vs Explicit Cursor
| Explicit Cursor | REF CURSOR |
|---|---|
| Declared with a specific query | Cursor variable |
| Query fixed in declaration | Query supplied at OPEN FOR |
| Less flexible | More flexible |
| Can be parameterized | Uses variables or dynamic SQL at runtime |
23. REF CURSOR vs Parameterized Cursor
Parameterized explicit cursor:
CURSOR emp_cursor(p_dept_id NUMBER) IS
SELECT *
FROM employees
WHERE department_id = p_dept_id;
REF CURSOR:
v_cursor SYS_REFCURSOR;
OPEN v_cursor FOR
SELECT *
FROM employees
WHERE department_id = 10;
Easy distinction:
Parameterized Cursor
↓
Fixed query + variable values
REF CURSOR
↓
Cursor variable + runtime result set
24. REF CURSOR vs SYS_REFCURSOR
REF CURSOR is the concept/type family. You can define your own type:
TYPE my_ref_cursor IS REF CURSOR;
SYS_REFCURSOR is Oracle's predefined weak REF CURSOR type.
v_cursor SYS_REFCURSOR;
25. Can a REF CURSOR be strongly typed?
Yes.
DECLARE
TYPE emp_cursor_type IS REF CURSOR
RETURN employees%ROWTYPE;
v_cursor emp_cursor_type;
BEGIN
OPEN v_cursor FOR
SELECT *
FROM employees;
CLOSE v_cursor;
END;
/
26. Can a weak REF CURSOR point to different queries?
Yes.
DECLARE
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name
FROM employees;
CLOSE v_cursor;
OPEN v_cursor FOR
SELECT department_id, department_name
FROM departments;
CLOSE v_cursor;
END;
/
27. Can we use a REF CURSOR in SQL directly?
Generally, no. A REF CURSOR is a PL/SQL cursor variable and result-set handle, not a table that can be queried with SELECT * FROM v_cursor.
28. Can we use a REF CURSOR in a Cursor FOR LOOP?
Yes, after opening the cursor.
DECLARE
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
FOR emp IN v_cursor
LOOP
DBMS_OUTPUT.PUT_LINE(
emp.employee_id || ' - ' ||
emp.first_name || ' - ' ||
emp.salary
);
END LOOP;
END;
/
29. REF CURSOR attributes
A REF CURSOR supports cursor attributes such as %ISOPEN, %FOUND, %NOTFOUND, and %ROWCOUNT.
30. Frequently Asked Questions
| Question | Answer |
|---|---|
| What is a REF CURSOR? | A cursor variable that points to a query result set. |
| What is SYS_REFCURSOR? | Oracle's predefined weak REF CURSOR type. |
| How do we open a REF CURSOR? | OPEN v_cursor FOR SELECT ...; |
| Can a REF CURSOR be returned from a procedure? | Yes, usually through OUT SYS_REFCURSOR. |
| Can a function return a REF CURSOR? | Yes. |
| Can a REF CURSOR be passed between procedures? | Yes. |
| Can it be used with dynamic SQL? | Yes. |
| Can a REF CURSOR be strong or weak? | Yes. |
| Is SYS_REFCURSOR strong or weak? | Weak. |
| Can we fetch from a REF CURSOR? | Yes. |
Important Exam Points
- REF CURSOR = cursor variable that points to a result set.
SYS_REFCURSORis a predefined weak REF CURSOR.- Open it using
OPEN v_cursor FOR SELECT ...; - Fetch using
FETCH v_cursor INTO ...; - Close using
CLOSE v_cursor; - A REF CURSOR can be passed as a parameter.
- A procedure can return a result set through
OUT SYS_REFCURSOR. - A function can return
SYS_REFCURSOR. - Strong REF CURSORs specify a return row type.
- Weak REF CURSORs don't specify a fixed return structure.
SYS_REFCURSORis weak.- REF CURSORs are useful for application-to-database result-set communication.
- They can be used with dynamic SQL.
- Cursor attributes such as
%ISOPEN,%FOUND,%NOTFOUND, and%ROWCOUNTcan be used appropriately. - REF CURSORs are different from normal explicit cursors because the query is associated with the cursor variable when it is opened.
Easy Memory Trick
NORMAL CURSOR
↓
Fixed query
↓
Fixed cursor definition
REF CURSOR
↓
Cursor variable
↓
OPEN FOR
↓
Result set
↓
FETCH
↓
Application / PL/SQL
REF CURSOR = a cursor variable used to point to and pass a result set.
No comments:
Post a Comment