I've have triggers on two separate tables that are designed to affect a third table, the problem is each trigger affects different rows.
The third table, C
, currently looking like this:
00000010 | R00000020 | R00000030 | R00000040 | R00000050 | R00000060
---------- ------------ ---------- ----------- ----------- ----------
R000000 | I | 0002 | | |
| | | 2 | 2 | 0025
I want something like this:
00000010 | R00000020 | R00000030 | R00000040 | R00000050 | R00000060
---------- ------------ ---------- ----------- ----------- ----------
R000000 | I | 0002 | 2 | 2 | 0025
| |
I could use a view to simply combine the output of the two source tables, however I'd rather use an actual table in this case.
Best Answer
Regarding your question about how to have triggers from two independent tables (
A
, andB
) insert rows into a third table (C
), you can certainly do that. Presumably bothA
andB
have a column that identifies the specific row inC
that needs to be updated.To prove this, I've created the two source tables
A
andB
, with a trigger on each table, that inserts into theC
table.Here we insert test data into
A
andB
, then show the rows inC
:The rows in
C
are:The code relies on the
RowID
value being identical in bothA
andB
; without some commonality, it is impossible to know which rows inC
need to be updated.The triggers above only inserts new rows into
C
if they don't already exist by using theOUTPUT
clause to insert theRowID
values into a temporary table which is subsequently used to prevent those rows from being inserted into theC
table. Only rows that don't already exist in the@t
table variable get inserted intoC
.If there is a high degree of concurrent activity against
A
andB
, with different processes potentially updating the same rows in those tables, it may be possible to attempt to insert duplicate rows intoC
. This would fail, causing the entire transaction to fail, rolling back the changes made by both the trigger inC
, as well as the changes made to eitherA
orB
. The code above does not account for this edge-case, and in fact has no error checking at all.The below answer and code is regarding the first "version" of your question, which was "can multiple triggers write to the same row".
You can very easily test that using:
If you run this, you'll see the following results:
This clearly proves that two separate
FOR INSERT
triggers can, and in fact do, update rows independently of each other. If both triggers are coded to affect the inserted rows, then that is what they will do.Unless you specify the trigger order using the
sys.sp_settriggerorder
stored procedure, it is not guaranteed that the trigger created first will fire first. If the logic contained in the these triggers depends on a certain logical firing order, you must ensure you specify the order. For instance:Also of note, you should realize triggers fire once for any given
INSERT
statement. Take for instance:In my tempdb, this created 101 rows, a sample of which is:
I coded my triggers to properly handle this by using a set-based approach to updating the underlying table with a
JOIN
to the special table,inserted
, which is a system-created virtual table containing the rows to be inserted into the table.