SQL Server 根据字段的值触发插入和/或更新的记录
Posted
技术标签:
【中文标题】SQL Server 根据字段的值触发插入和/或更新的记录【英文标题】:SQL Server trigger for an inserted and/or updated record, based on value of a field 【发布时间】:2013-02-22 16:33:41 【问题描述】:我有一个我认为非常简单的要求,但是因为我是新手,所以我不能让它正常工作。
我有一个充满客户数据的表,其 pk 为 cust_no
。当插入新的客户行并且电子邮件地址字段不为空时,我想将同一行中的日期字段设置为getdate()
。
如果客户记录用新的电子邮件地址更新,我也想做同样的事情,但同样,只有当电子邮件地址字段不为空,并且实际上用新的电子邮件地址更新时。
这样做的目的是生成在特定时间范围内收集的新电子邮件地址的报告。
任何帮助将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:需要记住的重要一点是很多人都犯了错误:SQL Server 中的触发器每条语句调用一次 - 而不是每行调用一次。
因此,如果您碰巧有一个 INSERT
或 UPDATE
语句一次插入或更新 50 行 - 您的触发器将被调用 once,伪表 (Inserted
和Deleted
在 UPDATE 情况下)将包含 50 行。在编写触发器时需要考虑到这一点。
INSERT 情况更简单 - 所以这里是这样:
-- CREATE after INSERT trigger
CREATE TRIGGER trgCustomerInsert
ON dbo.Customer AFTER INSERT
AS
-- update your "Customer" table
UPDATE dbo.Customer
SET SomeDateColumn = GETDATE() -- set date column to GETDATE()
FROM dbo.Customer c
INNER JOIN Inserted i ON c.cust_no = i.cust_no -- on all those rows inserted
WHERE c.Email IS NOT NULL -- where the e-mail address is NOT NULL
您基本上只需将 Inserted
伪表(包含刚插入的所有行 - 及其所有列值)与“真实”客户表相对,然后更新刚刚插入的所有客户行,以及电子邮件列不为空。
更新有点棘手 - 因为您只想更新电子邮件列之前为 NULL 的那些行,并且在更新之后现在不为 NULL。因此,您需要加入 Deleted
伪表,其中包含“旧”值(在 UPDATE 之前)。
所有已更新的行,Deleted
中电子邮件的旧值为 NULL,而 Customer 表中的当前值不是 NULL - 这些是您要更新日期的行列。
-- CREATE after UPDATE trigger
CREATE TRIGGER trgCustomerUpdate
ON dbo.Customer AFTER UPDATE
AS
-- update your "Customer" table
UPDATE dbo.Customer
SET SomeDateColumn = GETDATE() -- set date column to GETDATE()
FROM dbo.Customer c
INNER JOIN Deleted d ON c.cust_no = d.cust_no
WHERE
-- where new value of e-mail is NOT NULL
-- and the old value (in "Deleted") was in fact NULL
c.Email IS NOT NULL AND d.EMail IS NULL
【讨论】:
非常感谢,我从您的回复中学到了很多东西。我现在正在实施它,会让你知道它是怎么回事。感谢您指出整个批次都已更新,而不仅仅是一行。这是我在狭隘的处理方法中忽略的。 @user2100137:很高兴为您提供帮助!以上是关于SQL Server 根据字段的值触发插入和/或更新的记录的主要内容,如果未能解决你的问题,请参考以下文章
触发器实现对插入数据的字段更改 Oracle+SQL Server
如果插入的值与唯一约束冲突,则 SQL 触发器在插入时更新字段