我的Trigger遇到了一些麻烦。 它应该是:
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
示例表:
__________________________________________________
| value1 | value2 | counter | time(last updated) |
+------------------------------------------------+
| test1 | test2 | 1 | < 24h |
| test3 | test4 | 1 | > 24h |
| test3 | test4 | 1 | < 24h |
+------------------------------------------------+
输入:
INSERT INTO main_table(value1, value2, counter)
VALUES ('test3', 'test4', 1);
结果表:
__________________________________________________
| 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
+------------------------------------------------+
我明白为什么会发生这种情况(因为代码发现的历史值超过24小时,无视新的一个())但我不知道如何修复它。
答案 0 :(得分:1)
我认为如果inserted
包含行的混合,您的触发器仍会被破坏 - 因为您的IF
/ ELSE
结构会对要采取的操作做出单一决定。
最好有MERGE
,例如:
;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());
哪个应该替换整个触发器体。
顺便提一下,DATEDIFF
计算跨越边界的过渡次数,而不是计算精确差异(例如DATEDIFF(hour,'00:59','01:01')
为1)。如果你想接近24小时的截止时间,也考虑分钟和秒数,那么更好的比较是:
h.Time >= DATEADD(day,-1,GETDATE())
顺便提一下,还允许使用包含History
time
列的索引。
答案 1 :(得分:1)
- 像这样更改您的标准声明。它会工作。无论如何,你写的触发器真的不好。触发器应设计为处理set not records,因为一次批量插入/更新/删除只能触发一次。
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
答案 2 :(得分:0)
OMG我解决了它^^尝试修复它2个小时,当我发布到stackoverflow时我设法解决它^^
我做了什么:
更改了第二个“EXIST”测试:
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
)
为:
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
)