You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# G-7730: Avoid multiple DML events per trigger if primary key is assigned in trigger.
1
+
# G-7730: Avoid multiple DML events per trigger.
2
2
3
-
!!! warning "Major"
4
-
Efficiency, Reliability
3
+
!!! tip "Minor"
4
+
Maintainability, Testability
5
5
6
6
## Reason
7
7
8
-
If a trigger makes assignment to the primary key anywhere in the trigger code, that causes the session firing the trigger to take a lock on any child tables with a foreign key to this primary key. Even if the assignment is in for example an `if inserting` block and the trigger is fired by an `update` statement, such locks still happen unnecessarily. The issue is avoided by having one trigger for the insert containing the primary key assignment, and another trigger for the update. Or even better by handling the insert assignment as ´default on null´ clauses, so that only an `on update` trigger is needed.
8
+
Rather than a single trigger handling multiple DML events with separated blocks of `if inserting`, `if updating` and `if deleting`, modularity by individual triggers per DML event helps maintaining and testing the code. If most of the code is common for either DML event (only small pieces of code are individual) consider an exception to the rule and allow `if inserting`, `if updating` and `if deleting` blocks, or alternatively gather the common code in a procedure and let individual triggers handle the individual pieces of code plus call the procedure with the common code.
9
+
10
+
If the trigger makes assignment to a primary key and there are child tables with a foreign key referring to this primary key, the database can make undesirable table locks. If such is the case, you should always use individual triggers. See [G-7740](../../../../4-language-usage/7-stored-objects/7-triggers/g-7740) for details.
9
11
10
12
## Example (bad)
11
13
@@ -15,8 +17,7 @@ before insert or update
15
17
on departments for each row
16
18
begin
17
19
if inserting then
18
-
:new.department_id :=department_seq.nextval;
19
-
:new.created_date :=sysdate;
20
+
:new.created_date :=sysdate;
20
21
end if;
21
22
if updating then
22
23
:new.changed_date :=sysdate;
@@ -25,15 +26,14 @@ end;
25
26
/
26
27
```
27
28
28
-
## Example (better)
29
+
## Example (good)
29
30
30
31
```sql
31
32
create or replacetriggerdept_br_i
32
33
before insert
33
34
on departments for each row
34
35
begin
35
-
:new.department_id :=department_seq.nextval;
36
-
:new.created_date :=sysdate;
36
+
:new.created_date :=sysdate;
37
37
end;
38
38
/
39
39
@@ -45,18 +45,3 @@ begin
45
45
end;
46
46
/
47
47
```
48
-
49
-
## Example (good)
50
-
51
-
```sql
52
-
altertable department modify department_id default onnulldepartment_seq.nextval;
53
-
altertable department modify created_date default onnullsysdate;
# G-7740: Never handle multiple DML events per trigger if primary key is assigned in trigger.
2
+
3
+
!!! warning "Major"
4
+
Efficiency, Reliability
5
+
6
+
!!! missing "Unsupported in PL/SQL Cop Validators"
7
+
We cannot identify what the primary key column(s) are to check if assignment to a primary key is taking place in the trigger.
8
+
9
+
## Reason
10
+
11
+
If a trigger makes assignment to the primary key anywhere in the trigger code, that causes the session firing the trigger to take a lock on any child tables with a foreign key to this primary key. Even if the assignment is in for example an `if inserting` block and the trigger is fired by an `update` statement, such locks still happen unnecessarily. The issue is avoided by having one trigger for the insert containing the primary key assignment, and another trigger for the update. Or even better by handling the insert assignment as ´default on null´ clauses, so that only an `on update` trigger is needed.
12
+
13
+
## Example (bad)
14
+
15
+
```sql
16
+
create or replacetriggerdept_br_iu
17
+
before insert orupdate
18
+
on departments for each row
19
+
begin
20
+
if inserting then
21
+
:new.department_id :=department_seq.nextval;
22
+
:new.created_date :=sysdate;
23
+
end if;
24
+
if updating then
25
+
:new.changed_date :=sysdate;
26
+
end if;
27
+
end;
28
+
/
29
+
```
30
+
31
+
## Example (good)
32
+
33
+
```sql
34
+
create or replacetriggerdept_br_i
35
+
before insert
36
+
on departments for each row
37
+
begin
38
+
:new.department_id :=department_seq.nextval;
39
+
:new.created_date :=sysdate;
40
+
end;
41
+
/
42
+
43
+
create or replacetriggerdept_br_u
44
+
before update
45
+
on departments for each row
46
+
begin
47
+
:new.changed_date :=sysdate;
48
+
end;
49
+
/
50
+
```
51
+
52
+
## Example (best)
53
+
54
+
```sql
55
+
altertable department modify department_id default onnulldepartment_seq.nextval;
56
+
altertable department modify created_date default onnullsysdate;
0 commit comments