Skip to content

Commit

Permalink
Merge pull request #217 from Trivadis/feature/issue-213-new-rule-for-…
Browse files Browse the repository at this point in the history
…loop

add G-4387: Never use a FOR LOOP for a query that should return not more than one row.
  • Loading branch information
PhilippSalvisberg committed Mar 18, 2024
2 parents a5a4d12 + cd28542 commit 1406889
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
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

0 comments on commit 1406889

Please sign in to comment.