EDIT: Untested replacement
So I've just roughly written some SQL I think should work instead of everything including and below the SELECT Top 1
statement. The main issue I have with that part of your trigger is that it will only work for one-row updates, and it performs an INSERT then an UPDATE on that inserted data, which can be optimised.
INSERT into EpisodeHistory
SELECT
EpisodeID = d.EpisodeID,
eOwner = d.eOwner,
eDescription = iif(h.HistoryID is null, d.eDescription, ''),
eDescRef = isnull(h.HistoryID, 0),
hWhen = getDate(),
from deleted d
left join (
select
HistoryID, EpisodeID, eOwner, eDescription,
row_number() over (partition by EpisodeID, eOwner, eDescription ORDER BY HistoryID) as RowNumber
from EpisodeHistory
where eDescription <> ''
) h
on d.EpisodeID = h.EpisodeID
and d.eOwner = h.eOwner
and d.eDescription = h.eDescription
and h.RowNumber = 1
Rather than inserting the EpisodeHistory, then checking and updating based on the data we've just inserted, this code just does the operation all in one.
First I'll explain the left join. The point of the join is to find the HistoryID
of the earliest matching EpisodeHistory
row (since we want to put it in eDescRef
, right?). So we do a normal select of the EpisodeHistory
table, except we also add a column for row_number()
, which, when combined with the fact that we've put RowNumber = 1
in the join condition, will means it will only join to the first HistoryID
that matches. This makes sure that if there are two rows with the same EpisodeID
, eOwner
and eDescription
, it will only join to the one with the lowest HistoryID
.
Now the actual columns that are inserted are fairly simple. If the left join fails (if no rows in EpisodeHistory match), selecting h.HistoryID
will return NULL
. Therefore, eDescription = iif(h.HistoryID is null, d.eDescription, '')
means that if a HistoryID
was not found in the join, it will just do a normal insert of eDescription
. If one was found, it will blank that field. The next line is fairly simple in that it inserts HistoryID
if the join happened, otherwise it puts in 0.
Since the entire operation can be done in one statement like above, so you can ignore that bit I said above about temporary tables and an output
clause.
This code above also has the added bonus of working for multiple-row updates.