Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add G-4387: Never use a FOR LOOP for a query that should return not more than one row. #217

Merged
merged 2 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# G-4387: Never use a FOR LOOP for a query that should return not more than one row.

!!! bug "Blocker"
Reliability, Efficiency, Readability

!!! missing "Unsupported in db\* CODECOP Validators"
Without access to the Oracle Data Dictionary, we cannot determine the number of rows to be processed.

## Reason

A `for loop` can hide a `too_many_rows` exception. The more complex a query is, the higher is the risk that more than one row will be processed.
This affects performance and can lead to a wrong result.

A `for loop` can also hide a `no_data_found` exception and the reader cannot determine whether this is intentional or not.

## Example (bad)

``` sql
create or replace package body employee_api is
function emp_name(in_empno in integer) return varchar2 is -- NOSONAR: non-deterministic
l_ename emp.ename%type;
begin
<<fetch_name>>
for r in (
select ename
from emp
where empno = in_empno
)
loop
l_ename := r.ename;
end loop fetch_name;
return l_ename;
end emp_name;
end employee_api;
/
```

## Example (good)

``` sql
create or replace package body employee_api is
function emp_name(in_empno in integer) return varchar2 is -- NOSONAR: non-deterministic
l_ename emp.ename%type;
begin
select ename
into l_ename
from emp
where empno >= in_empno;
return l_ename;
exception
when no_data_found then
return null;
when too_many_rows then
raise;
end emp_name;
end employee_api;
/
```
1 change: 1 addition & 0 deletions docs/9-appendix/appendix.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ n/a | 4365 | Never use unconditional CONTINUE or EXIT in a loop. | Major | | |
46 | 4375 | Always use EXIT WHEN instead of an IF statement to exit from a loop. | Minor | | | &#10008; | | | | |
47 | 4380 | Try to label your EXIT WHEN statements. | Minor | | | &#10008; | | | | |
48 | 4385 | Never use a cursor for loop to check whether a cursor returns data. | Critical | | &#10008; | | | | | |
n/a | 4387 | !!!CHARACTERISTIC ERROR!!! | Blocker | | &#10008; | | | &#10008; | | |
49 | 4390 | Avoid use of unreferenced FOR loop indexes. | Major | | &#10008; | | | | | |
50 | 4395 | Avoid hard-coded upper or lower bound values with FOR loops. | Minor | &#10008; | | &#10008; | | | | |
n/a | 5010 | Try to use a error/logging framework for your application. | Critical | | | | | &#10008; | &#10008; | | &#10008;
Expand Down
Loading