Reputation: 3493
I'm having a bit of a trouble with my Trigger. It's supposed to:
Sloppy pseudocode:
IF NOT EXISTS ( --if the value isn't in the history table
SELECT History.value1 FROM History, INSERTED
WHERE History.value1 LIKE INSERTED.value1
AND History.value2 LIKE INSERTED.value2
)
OR EXISTS ( --or if it has been added over 24h ago
SELECT History.value1 FROM History, INSERTED
WHERE History.value1 LIKE INSERTED.value1
AND History.value2 LIKE INSERTED.value2
AND DATEDIFF(HOUR,History.time, GETDATE()) > 24
)
BEGIN --Insert it
INSERT INTO History(value1, value2, counter, time)
SELECT value1, value2, counter GETDATE() FROM INSERTED
END
ELSE
BEGIN -- else, increase counter and add new time
UPDATE History
SET History.time = GETDATE(),
History.Items = History.Items + INSERTED.Items
FROM History
JOIN INSERTED ON History.value1 = INSERTED.value1
AND History.value2 = INSERTED.value2
AND DATEDIFF(HOUR, _History.time, GETDATE()) < 24;
END
example table:
__________________________________________________
| value1 | value2 | counter | time(last updated) |
+------------------------------------------------+
| test1 | test2 | 1 | < 24h |
| test3 | test4 | 1 | > 24h |
| test3 | test4 | 1 | < 24h |
+------------------------------------------------+
input:
INSERT INTO main_table(value1, value2, counter)
VALUES ('test3', 'test4', 1);
resulting table:
__________________________________________________
| value1 | value2 | counter | time(last updated) |
+------------------------------------------------+
| test1 | test2 | 1 | < 24h |
| test3 | test4 | 1 | > 24h |
| test3 | test4 | 1 | < 24h | <--This counter+time should be updated
| test3 | test4 | 1 | < 24h | <--This row shouldn't be added
+------------------------------------------------+
I Understand WHY this happens (because the code finds a history value thats over 24h, disregarding the newer one(s)) but I dont know how to fix it.
Upvotes: 0
Views: 99
Reputation: 11
--Change your criteria statements like this. it will work. Anyway, the trigger you write really not good. Triggers should design to deal with set not records, as one batch insert/update/delete only can trigger once.
IF NOT EXISTS ( --if the value isn't in the history table
SELECT History.value1 FROM History, INSERTED
WHERE History.value1 LIKE INSERTED.value1
AND History.value2 LIKE INSERTED.value2
)
OR EXISTS ( --or if it has been added over 24h ago
SELECT INSERTED.value1
FROM INSERTED
cross apply
(select max(History.[time]) mx_time
from History
where History.value1 LIKE INSERTED.value1
AND History.value2 LIKE INSERTED.value2
) as t
WHERE DATEDIFF(HOUR,t.mx_time, GETDATE()) >= 24
)
BEGIN --Insert it
INSERT INTO History(value1, value2, items, time)
SELECT value1, value2, items, GETDATE() FROM INSERTED
END
ELSE
BEGIN -- else, increase counter and add new time
UPDATE History
SET History.time = GETDATE(),
History.Items = History.Items + INSERTED.Items
FROM History
JOIN INSERTED ON History.value1 = INSERTED.value1
AND History.value2 = INSERTED.value2
AND DATEDIFF(HOUR, History.time, GETDATE()) < 24;
END
Upvotes: 1
Reputation: 239646
I think your trigger is still broken if inserted
contains a mixture of rows - since your IF
/ELSE
structure makes a single decision on what action to take.
It would be better to have a MERGE
, something like:
;MERGE INTO History h USING INSERTED i
ON h.Value1 = i.Value1 and h.Value2 = i.Value2 and
DATEDIFF(HOUR,h.time, GETDATE()) <= 24
WHEN MATCHED THEN
UPDATE SET time = GETDATE(), Items = h.Items + i.Items
WHEN NOT MATCHED THEN
INSERT (Value1,Value2,Items,time)
VALUES (i.Value1,i.Value2,i.Items,GETDATE());
Which should replace your whole trigger body.
Incidentally, DATEDIFF
counts the number of transitions across boundaries, rather than computing an exact difference (E.g. DATEDIFF(hour,'00:59','01:01')
is 1). If you want to get closer to a 24 hour cutoff which also considers minutes and seconds, a better comparison would be:
h.Time >= DATEADD(day,-1,GETDATE())
Which incidentally would also allow an index that includes History
's time
column to be used.
Upvotes: 1
Reputation: 3493
OMG I solved it ^^ Been trying to fix it for like 2 hours and just when I post it to stackoverflow I manage to fix it ^^
What I did:
Changed the second "EXIST" test from:
OR EXISTS ( --or if it has been added over 24h ago
SELECT History.value1 FROM History, INSERTED
WHERE History.value1 LIKE INSERTED.value1
AND History.value2 LIKE INSERTED.value2
AND DATEDIFF(HOUR,History.time, GETDATE()) > 24
)
to:
OR NOT EXISTS ( --or if it has been added over 24h ago
SELECT History.value1 FROM History, INSERTED
WHERE NOT History.value1 LIKE INSERTED.value1
OR History.value2 LIKE INSERTED.value2
OR DATEDIFF(HOUR,History.time, GETDATE()) > 24
)
Upvotes: 0