我有一个SQL触发器,如下所示
GO
create trigger ExpDateCheckCard
On Card
FOR Insert, Update
As
Declare @expDate as DateTime
Select @expDate = inserted.ExpirationDate from inserted
if (YEAR(@expDate) < 1971 )
BEGIN
UPdate Card set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
where inserted.RecordID = Card.RecordID
END
如果我在触发器运行时插入/更新的每个记录的触发器是正确的,它将检查该记录的ExpirationDate列中的YEAR,如果该值小于1971,那么它将使用日期更新它更新查询。
奇怪的是它没有按预期工作。
if条件似乎不起作用。
此特定触发器有什么问题。
答案 0 :(得分:3)
是 - 你写这个触发器的方式肯定存在根本性的错误。
SQL Server(假设你正在使用的)将触发每行不会触发一次(包括你自己在内的很多人)似乎认为 - 触发器被激活每批次,这可能会更新或者一次插入10,20,50行。
因此,触发器中的Inserted
伪表可以(并且将!)包含多行 - 在这种情况下 - 您的语句究竟选择了什么?
Select @expDate = inserted.ExpirationDate from inserted
要么你只得到一个randon行(50个)并处理(并忽略所有49个其他行),否则你会收到错误....
你需要记住你的触发器 - 你必须总是假设Inserted
(和Deleted
)将包含多行!
因此,您需要将触发器更改为:
CREATE TRIGGER ExpDateCheckCard
ON dbo.Card
FOR Insert, Update
AS
UPDATE dbo.Card
SET ExpirationDate = '1900-01-01 00:00:00'
FROM dbo.Card c
INNER JOIN inserted i ON i.RecordID = c.RecordID
WHERE YEAR(i.ExpirationDate) < 1971
(我还将旧式JOIN语法(以逗号分隔的表格列表)更改为自1992年以来一直存在的ANSI标准 - 请不要使用逗号 - 分隔的表格列表!使用正确的 ANSI JOIN 。有关更多背景信息,请参阅此博客文章:Bad habits to kick : using old-style JOINs)
答案 1 :(得分:0)
试试这个:
create trigger ExpDateCheckCard
On Card
FOR Insert, Update
As
BEGIN
Declare @expDate as DateTime
Select @expDate = inserted.ExpirationDate from inserted
if (YEAR(@expDate) < 1971 ) Begin
UPdate Card set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
where inserted.RecordID = Card.RecordID
end
END
答案 2 :(得分:0)
您必须尝试此代码
CREATE TRIGGER ExpDateCheckCard AFTER INSERT,Update ON Card
FOR EACH ROW
Declare @expDate as DateTime
Select @expDate = inserted.ExpirationDate from inserted
if (YEAR(@expDate) < 1971 )
BEGIN
update Card
set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
where inserted.RecordID = Card.RecordID
END