Skip to content

Changes for version 4.0 #86

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

Merged
merged 19 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2a0b3a2
Fix #81 - Removed G-7240 and replaced with G-7160 and G-7170
kibeha Aug 26, 2020
efe7c60
Fix #22 - Added Transaction Control category with rules G-3210 and G-…
kibeha Aug 26, 2020
29d1079
New Trivadis style for PDF cover. Slight addition to introduction.
kibeha Aug 26, 2020
81c2836
Fix #22 - Re-numbered falsely created rules G-3210 and G-3220 to G-33…
kibeha Sep 2, 2020
ca35d65
Fix #57 - Altered rule to all lowercase. Added footnote on reason and…
kibeha Sep 2, 2020
5607a7c
Fix #25 - Created rule G-7240: Never use RETURN in package initializa…
kibeha Sep 2, 2020
e414069
Fix #27 - Created rule G-7720: Never use multiple UPDATE OF in trigge…
kibeha Sep 2, 2020
bc849ca
Fix #31 - Created rule G-4250: Avoid using identical conditions in di…
kibeha Sep 16, 2020
9d618b5
Fix #85 - Warn about NULL issues in rule G-4220
kibeha Sep 16, 2020
c2f4762
Fix #38 - Created rule G-3195: Always use wildcards in a LIKE clause.
kibeha Sep 16, 2020
7a6c975
Fix #57 - Lowercasing inline keywords in text and a few code samples …
kibeha Sep 16, 2020
5af501b
Fix #30 - Created rule G-7330: Always assign values to OUT parameters.
kibeha Sep 16, 2020
e10f537
Fix #48 - Created rule G-2135: Avoid assigning values to local variab…
kibeha Sep 16, 2020
865aac4
Fix #84 - Created rule G-7730: Avoid multiple DML events per trigger …
kibeha Sep 16, 2020
16d67a4
Fix #44 - Created rule G-4260: Avoid inverting boolean conditions.
kibeha Sep 16, 2020
cb2ff5b
Fix #45 - Created rule G-4270: Avoid comparing boolean values to bool…
kibeha Sep 16, 2020
93abd1b
Fix #79 - Added phrasing and slight reworking of sample code in G-723…
kibeha Sep 16, 2020
9d2d2f5
Fix #78 - Added paragraph explaining that exceptions to Rule G-1050 e…
kibeha Sep 16, 2020
e2c82be
Fix #77 - Added explanation about exception to rule G-5040 in case of…
kibeha Sep 16, 2020
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
2 changes: 1 addition & 1 deletion docs/1-introduction/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ There are basically two types of standards.

2. Controversial

Almost every rule/guildeline falls into this category. An example of this category is [3 space indention](../../3-coding-style/coding-style/#rules). - Why not 2 or 4 or even 8? Why not use tabs? You can argue in favor of all these options. In most cases it does not really matter which option you choose. Being consistent is more important. In this case it will make the code easier to read.
Almost every rule/guideline falls into this category. An example of this category is [3 space indention](../../3-coding-style/coding-style/#rules). - Why not 2 or 4 or even 8? Why not use tabs? You can argue in favor of all these options. In most cases it does not really matter which option you choose. Being consistent is more important. In this case it will make the code easier to read.

For very controversial rules, we have started to include the reasoning either as a footnote or directly in the text.

Expand Down
4 changes: 2 additions & 2 deletions docs/2-naming-conventions/naming-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
4. Avoid long abbreviations. Abbreviations should be shorter than 5 characters.
5. Any abbreviations must be widely known and accepted.
6. Create a glossary with all accepted abbreviations.
7. Never use ORACLE keywords as names. A list of ORACLEs keywords may be found in the dictionary view `V$RESERVED_WORDS`.
8. Avoid adding redundant or meaningless prefixes and suffixes to identifiers.<br/>Example: `CREATE TABLE emp_table`.
7. Never use ORACLE keywords as names. A list of ORACLEs keywords may be found in the dictionary view `v$reserved_words`.
8. Avoid adding redundant or meaningless prefixes and suffixes to identifiers.<br/>Example: `create table emp_table`.
9. Always use one spoken language (e.g. English, German, French) for all objects in your application.
10. Always use the same names for elements with the same meaning.

Expand Down
58 changes: 32 additions & 26 deletions docs/3-coding-style/coding-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

Rule | Description
:--: | -----------
1 | Keywords are written uppercase, names are written in lowercase.
2 | 3 space indention[^2].
1 | Keywords and names are written in lowercase[^2].
2 | 3 space indention[^3].
3 | One command per line.
4 | Keywords `LOOP`, `ELSE`, `ELSIF`, `END IF`, `WHEN` on a new line.
4 | Keywords `loop`, `else`, `elsif`, `end if`, `when` on a new line.
5 | Commas in front of separated elements.
6 | Call parameters aligned, operators aligned, values aligned.
7 | SQL keywords are right aligned within a SQL command.
Expand All @@ -18,34 +18,34 @@ Rule | Description

### Example

```
PROCEDURE set_salary(in_employee_id IN employees.employee_id%TYPE) IS
CURSOR c_employees(p_employee_id IN employees.employee_id%TYPE) IS
SELECT last_name
``` sql
procedure set_salary(in_employee_id in employees.employee_id%type) is
cursor c_employees(p_employee_id in employees.employee_id%type) is
select last_name
,first_name
,salary
FROM employees
WHERE employee_id = p_employee_id
ORDER BY last_name
from employees
where employee_id = p_employee_id
order by last_name
,first_name;

r_employee c_employees%ROWTYPE;
l_new_salary employees.salary%TYPE;
BEGIN
OPEN c_employees(p_employee_id => in_employee_id);
FETCH c_employees INTO r_employee;
CLOSE c_employees;
r_employee c_employees%rowtype;
l_new_salary employees.salary%type;
begin
open c_employees(p_employee_id => in_employee_id);
fetch c_employees into r_employee;
close c_employees;

new_salary (in_employee_id => in_employee_id
,out_salary => l_new_salary);

-- Check whether salary has changed
IF r_employee.salary <> l_new_salary THEN
UPDATE employees
SET salary = l_new_salary
WHERE employee_id = in_employee_id;
END IF;
END set_salary;
if r_employee.salary <> l_new_salary then
update employees
set salary = l_new_salary
where employee_id = in_employee_id;
end if;
end set_salary;
```

## Code Commenting
Expand All @@ -70,7 +70,7 @@ Tag | Meaning | Example

This is an example using the documentation capabilities of SQL Developer.

```
``` sql
/**
Check whether we passed a valid sql name

Expand All @@ -80,15 +80,21 @@ Check whether we passed a valid sql name

<b>Call Example:</b>
<pre>
SELECT TVDAssert.valid_sql_name('TEST') from dual;
SELECT TVDAssert.valid_sql_name('123') from dual
select TVDAssert.valid_sql_name('TEST') from dual;
select TVDAssert.valid_sql_name('123') from dual
</pre>
*/
```

[^2]:
It used to be good practice to use uppercase keywords and lowercase names to help visualize code structure.
But practically all editors support more or less advanced color highlighting of code, similar to the examples in these guidelines.
Hence as of version 4.0 we are now recommending all lowercase, as this is easier and faster for the brain to process.
You may choose to prefer the old rule - however, it is important to always be consistent, like for example keywords always in uppercase and names always in lowercase.

[^3]:
Tabs are not used because the indentation depends on the editor configuration.
We want to ensure that the code looks the same, indepenent of the editor used.
We want to ensure that the code looks the same, independent of the editor used.
Hence, no tabs. But why not use 8 spaces? That's the traditional value for a tab.
When writing a package function the code in the body has an indentation of 3.
That's 24 characters as a starting point for the code. We think it's too much.
Expand Down
38 changes: 19 additions & 19 deletions docs/4-language-usage/1-general/g-1010.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,32 @@ It's a good alternative for comments to indicate the start and end of a named pr

## Example (bad)

```
BEGIN
BEGIN
NULL;
END;

BEGIN
NULL;
END;
END;
``` sql
begin
begin
null;
end;

begin
null;
end;
end;
/
```

## Example (good)

```
BEGIN
``` sql
begin
<<prepare_data>>
BEGIN
NULL;
END prepare_data;
begin
null;
end prepare_data;

<<process_data>>
BEGIN
NULL;
END process_data;
END good;
begin
null;
end process_data;
end good;
/
```
94 changes: 47 additions & 47 deletions docs/4-language-usage/1-general/g-1020.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,84 +8,84 @@
Use a label directly in front of loops and nested anonymous blocks:

* To give a name to that portion of code and thereby self-document what it is doing.
* So that you can repeat that name with the END statement of that block or loop.
* So that you can repeat that name with the `end` statement of that block or loop.

## Example (bad)

```
DECLARE
i INTEGER;
co_min_value CONSTANT INTEGER := 1;
co_max_value CONSTANT INTEGER := 10;
co_increment CONSTANT INTEGER := 1;
BEGIN
``` sql
declare
i integer;
co_min_value constant integer := 1;
co_max_value constant integer := 10;
co_increment constant integer := 1;
begin
<<prepare_data>>
BEGIN
NULL;
END;
begin
null;
end;

<<process_data>>
BEGIN
NULL;
END;
begin
null;
end;

i := co_min_value;
<<while_loop>>
WHILE (i <= co_max_value)
LOOP
while (i <= co_max_value)
loop
i := i + co_increment;
END LOOP;
end loop;

<<basic_loop>>
LOOP
EXIT basic_loop;
END LOOP;
loop
exit basic_loop;
end loop;

<<for_loop>>
FOR i IN co_min_value..co_max_value
LOOP
for i in co_min_value..co_max_value
loop
sys.dbms_output.put_line(i);
END LOOP;
END;
end loop;
end;
/
```

## Example (good)

```
DECLARE
i INTEGER;
co_min_value CONSTANT INTEGER := 1;
co_max_value CONSTANT INTEGER := 10;
co_increment CONSTANT INTEGER := 1;
BEGIN
``` sql
declare
i integer;
co_min_value constant integer := 1;
co_max_value constant integer := 10;
co_increment constant integer := 1;
begin
<<prepare_data>>
BEGIN
NULL;
END prepare_data;
begin
null;
end prepare_data;

<<process_data>>
BEGIN
NULL;
END process_data;
begin
null;
end process_data;

i := co_min_value;
<<while_loop>>
WHILE (i <= co_max_value)
LOOP
while (i <= co_max_value)
loop
i := i + co_increment;
END LOOP while_loop;
end loop while_loop;

<<basic_loop>>
LOOP
EXIT basic_loop;
END LOOP basic_loop;
loop
exit basic_loop;
end loop basic_loop;

<<for_loop>>
FOR i IN co_min_value..co_max_value
LOOP
for i in co_min_value..co_max_value
loop
sys.dbms_output.put_line(i);
END LOOP for_loop;
END;
end loop for_loop;
end;
/
```
70 changes: 35 additions & 35 deletions docs/4-language-usage/1-general/g-1030.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,45 @@ Unused variables decrease the maintainability and readability of your code.

## Example (bad)

```
CREATE OR REPLACE PACKAGE BODY my_package IS
PROCEDURE my_proc IS
l_last_name employees.last_name%TYPE;
l_first_name employees.first_name%TYPE;
co_department_id CONSTANT departments.department_id%TYPE := 10;
e_good EXCEPTION;
BEGIN
SELECT e.last_name
INTO l_last_name
FROM employees e
WHERE e.department_id = co_department_id;
EXCEPTION
WHEN no_data_found THEN NULL; -- handle_no_data_found;
WHEN too_many_rows THEN null; -- handle_too_many_rows;
END my_proc;
END my_package;
``` sql
create or replace package body my_package is
procedure my_proc is
l_last_name employees.last_name%type;
l_first_name employees.first_name%type;
co_department_id constant departments.department_id%type := 10;
e_good exception;
begin
select e.last_name
into l_last_name
from employees e
where e.department_id = co_department_id;
exception
when no_data_found then null; -- handle_no_data_found;
when too_many_rows then null; -- handle_too_many_rows;
end my_proc;
end my_package;
/
```

## Example (good)

```
CREATE OR REPLACE PACKAGE BODY my_package IS
PROCEDURE my_proc IS
l_last_name employees.last_name%TYPE;
co_department_id CONSTANT departments.department_id%TYPE := 10;
e_good EXCEPTION;
BEGIN
SELECT e.last_name
INTO l_last_name
FROM employees e
WHERE e.department_id = co_department_id;

RAISE e_good;
EXCEPTION
WHEN no_data_found THEN NULL; -- handle_no_data_found;
WHEN too_many_rows THEN null; -- handle_too_many_rows;
END my_proc;
END my_package;
``` sql
create or replace package body my_package is
procedure my_proc is
l_last_name employees.last_name%type;
co_department_id constant departments.department_id%type := 10;
e_good exception;
begin
select e.last_name
into l_last_name
from employees e
where e.department_id = co_department_id;

raise e_good;
exception
when no_data_found then null; -- handle_no_data_found;
when too_many_rows then null; -- handle_too_many_rows;
end my_proc;
end my_package;
/
```
Loading