1. What are Cursor Attributes?
Cursor attributes are properties that tell you what happened during cursor processing.
For an implicit cursor:
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
SQL%ISOPEN
For an explicit cursor:
emp_cursor%FOUND
emp_cursor%NOTFOUND
emp_cursor%ROWCOUNT
emp_cursor%ISOPEN
2. What are the four main Cursor Attributes?
| Attribute | Meaning |
|---|---|
| %FOUND | Indicates whether a row was found or affected |
| %NOTFOUND | Indicates whether no row was found or affected |
| %ROWCOUNT | Number of rows affected or fetched |
| %ISOPEN | Indicates whether an explicit cursor is open |
Memory trick: F-N-R-I = Found, Not Found, Row Count, Is Open
3. What is %FOUND?
%FOUND tells whether the most recent cursor operation successfully found or affected a row, as applicable.
Explicit cursor example:
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO v_id, v_name;
IF emp_cursor%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Row found');
END IF;
CLOSE emp_cursor;
END;
/
If the fetch retrieves a row, the output is:
Row found
4. What is SQL%FOUND?
For an implicit cursor, use SQL%FOUND.
Example:
BEGIN
UPDATE employees
SET salary = salary + 1000
WHERE employee_id = 101;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee updated');
END IF;
END;
/
If employee 101 was updated, %FOUND is TRUE.
5. What is %NOTFOUND?
%NOTFOUND indicates that the most recent cursor operation did not find or affect a row, as applicable. It is particularly important when processing an explicit cursor.
Example:
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_id, v_name;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_name);
END LOOP;
CLOSE emp_cursor;
END;
/
Flow:
FETCH
↓
Row found?
↓
YES → Process row
↓
FETCH again
↓
No row
↓
%NOTFOUND = TRUE
↓
EXIT
6. What is SQL%NOTFOUND?
For an implicit cursor, SQL%NOTFOUND can be used after DML to determine that no rows were affected.
Example:
BEGIN
DELETE FROM employees
WHERE employee_id = 9999;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No employee deleted');
END IF;
END;
/
If employee 9999 does not exist, the output is:
No employee deleted
7. What is %ROWCOUNT?
%ROWCOUNT tells the number of rows processed. For an explicit cursor, it gives the number of rows fetched so far.
Example:
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_id, v_name;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(
'Rows fetched: ' || emp_cursor%ROWCOUNT
);
END LOOP;
CLOSE emp_cursor;
END;
/
The values increase as rows are fetched:
Rows fetched: 1
Rows fetched: 2
Rows fetched: 3
...
8. What is SQL%ROWCOUNT?
For an implicit cursor, SQL%ROWCOUNT tells the number of rows affected by the most recent DML statement.
Example:
BEGIN
UPDATE employees
SET salary = salary + 2000
WHERE department_id = 10;
DBMS_OUTPUT.PUT_LINE(
'Rows updated: ' || SQL%ROWCOUNT
);
END;
/
If 10 employees are updated, the output is:
Rows updated: 10
9. What is %ISOPEN?
%ISOPEN tells whether an explicit cursor is currently open.
Example:
DECLARE
CURSOR emp_cursor IS
SELECT employee_id
FROM employees;
BEGIN
OPEN emp_cursor;
IF emp_cursor%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is open');
END IF;
CLOSE emp_cursor;
END;
/
Output:
Cursor is open
10. What is SQL%ISOPEN?
For an implicit cursor, Oracle manages the cursor automatically.
Example:
BEGIN
UPDATE employees
SET salary = salary + 1000
WHERE employee_id = 101;
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Open');
ELSE
DBMS_OUTPUT.PUT_LINE('Closed');
END IF;
END;
/
After the statement completes, the implicit cursor is closed, so the result is:
Closed
Exam point: SQL%ISOPEN is always FALSE after the implicit SQL statement has completed.
11. Difference between implicit and explicit cursor attributes
| Implicit Cursor | Explicit Cursor |
|---|---|
| SQL%FOUND | emp_cursor%FOUND |
| SQL%NOTFOUND | emp_cursor%NOTFOUND |
| SQL%ROWCOUNT | emp_cursor%ROWCOUNT |
| SQL%ISOPEN | emp_cursor%ISOPEN |
12. Example of all four explicit cursor attributes
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
v_id employees.employee_id%TYPE;
v_name employees.first_name%TYPE;
BEGIN
OPEN emp_cursor;
IF emp_cursor%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is open');
END IF;
LOOP
FETCH emp_cursor INTO v_id, v_name;
IF emp_cursor%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee: ' || v_name);
DBMS_OUTPUT.PUT_LINE('Rows fetched: ' || emp_cursor%ROWCOUNT);
END IF;
EXIT WHEN emp_cursor%NOTFOUND;
END LOOP;
CLOSE emp_cursor;
IF NOT emp_cursor%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is closed');
END IF;
END;
/
This demonstrates %ISOPEN, %FOUND, %ROWCOUNT, and %NOTFOUND.
13. Why is %NOTFOUND usually checked after FETCH?
Because the cursor needs to attempt a fetch before it can determine whether another row exists.
LOOP
FETCH emp_cursor INTO v_id, v_name;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_name);
END LOOP;
14. What happens to %ROWCOUNT after each FETCH?
For an explicit cursor:
First successful FETCH → %ROWCOUNT = 1
Second successful FETCH → %ROWCOUNT = 2
Third successful FETCH → %ROWCOUNT = 3
15. Example of %ROWCOUNT with INSERT
BEGIN
INSERT INTO employees
(employee_id, first_name, salary)
VALUES
(101, 'Ravi', 50000);
DBMS_OUTPUT.PUT_LINE(
'Rows inserted: ' || SQL%ROWCOUNT
);
END;
/
Output:
Rows inserted: 1
16. Example of %ROWCOUNT with DELETE
BEGIN
DELETE FROM employees
WHERE department_id = 20;
DBMS_OUTPUT.PUT_LINE(
'Rows deleted: ' || SQL%ROWCOUNT
);
END;
/
If 7 rows were deleted, the output is:
Rows deleted: 7
17. Example of %ROWCOUNT with UPDATE
BEGIN
UPDATE employees
SET salary = 60000
WHERE department_id = 10;
IF SQL%ROWCOUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' employees updated');
ELSE
DBMS_OUTPUT.PUT_LINE('No employees updated');
END IF;
END;
/
18. Can %ROWCOUNT be zero?
Yes.
BEGIN
DELETE FROM employees
WHERE employee_id = 9999;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
END;
/
If the employee does not exist, the output is:
0
19. Can %FOUND and %NOTFOUND both be TRUE?
No. For a given cursor state, they represent opposite conditions.
Conceptually:
%FOUND = TRUE → row found
%NOTFOUND = TRUE → row not found
20. What happens to cursor attributes after another SQL statement?
Cursor attributes can be affected by subsequent SQL operations.
Best practice: save the value if you need it later.
DECLARE
v_count NUMBER;
BEGIN
UPDATE employees
SET salary = salary + 1000
WHERE department_id = 10;
v_count := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Employees updated: ' || v_count);
END;
/
21. What happens if %NOTFOUND is used before the first FETCH?
For an explicit cursor, you should not use %NOTFOUND as the loop condition before the first fetch. Use the standard fetch-then-exit pattern.
22. What happens if you use %FOUND after a failed FETCH?
After a fetch that does not retrieve a row:
%FOUND = FALSE
%NOTFOUND = TRUE
23. Cursor Attributes with Cursor FOR LOOP
In a Cursor FOR LOOP, you generally do not need to manually check %FOUND or %NOTFOUND.
BEGIN
FOR emp IN (
SELECT employee_id, first_name
FROM employees
)
LOOP
DBMS_OUTPUT.PUT_LINE(emp.first_name);
END LOOP;
END;
/
24. Explicit Cursor Attribute Example with %ROWTYPE
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, first_name, salary
FROM employees;
v_emp emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_emp;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ID: ' || v_emp.employee_id);
DBMS_OUTPUT.PUT_LINE('Name: ' || v_emp.first_name);
DBMS_OUTPUT.PUT_LINE('Rows fetched: ' || emp_cursor%ROWCOUNT);
END LOOP;
CLOSE emp_cursor;
END;
/
25. Frequently Asked Questions
| Question | Answer |
|---|---|
| What are cursor attributes? | Properties that provide information about cursor processing. |
| What are the four main attributes? | %FOUND, %NOTFOUND, %ROWCOUNT, %ISOPEN |
| Which attribute tells whether a row was found? | %FOUND |
| Which attribute tells whether no row was found? | %NOTFOUND |
| Which attribute gives the number of rows processed? | %ROWCOUNT |
| Which attribute tells whether a cursor is open? | %ISOPEN |
| What is the syntax for an implicit cursor attribute? | SQL%ROWCOUNT |
| What is the syntax for an explicit cursor attribute? | emp_cursor%ROWCOUNT |
| Which attribute is commonly used to exit an explicit cursor loop? | %NOTFOUND |
| What does %ROWCOUNT mean for an explicit cursor? | The number of rows fetched so far. |
| What does SQL%ROWCOUNT mean for an implicit cursor? | The number of rows affected by the SQL statement. |
| What is SQL%ISOPEN after an implicit SQL statement completes? | FALSE. |
Important Exam Points
- Cursor attributes provide information about cursor processing.
- The four main attributes are
%FOUND,%NOTFOUND,%ROWCOUNT, and%ISOPEN. - Implicit cursor syntax uses
SQL%attribute. - Explicit cursor syntax uses
cursor_name%attribute. %FOUNDmeans row found or affected.%NOTFOUNDmeans no row found or affected.%ROWCOUNTmeans number of rows processed.- For explicit cursors,
%ROWCOUNTincreases after successful fetches. %ISOPENindicates cursor open status.SQL%ISOPENis FALSE after the implicit statement has completed.%NOTFOUNDis commonly used to exit explicit cursor loops.- Cursor attributes relate to the most recent relevant cursor operation.
Quick Revision Table
| Attribute | Explicit Cursor | Implicit Cursor |
|---|---|---|
| Found | emp_cursor%FOUND | SQL%FOUND |
| Not found | emp_cursor%NOTFOUND | SQL%NOTFOUND |
| Row count | emp_cursor%ROWCOUNT | SQL%ROWCOUNT |
| Is open | emp_cursor%ISOPEN | SQL%ISOPEN |
One-line memory trick: FOUND = Did it find? NOTFOUND = Did it fail to find? ROWCOUNT = How many? ISOPEN = Is the cursor open?
No comments:
Post a Comment