2014-02-12 103 views
0

我有Customer表。为了简化可以说我有两列触发后更新SQL

Id 
Name 

我有第二个表,我想更新(Log)只有当我的客户的变化Id列。是的,你听说我的主键(Id)会改变!

我拿了一捅但被拉到NewIdCustomer表中的第一个记录不是更新的记录

ALTER TRIGGER [dbo].[tr_ID_Modified] 
    ON [dbo].[customer] 
AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE (Id) 
    BEGIN 
     UPDATE [log] 
     SET NewId = Id 
     FROM customer 
    END 
    END 
+2

PK更改和触发器很难/不可能得到正确。 “插入”和“删除”表包含现在和现在在语句启动之前的行。但是,通过这种方式你可以在这两张表之间匹配行。你能不能在这个表中添加一个代理(不变的)唯一密钥?这将使写触发器更加直接。 –

+0

我的建议答案适合您吗?你会接受答案,以便其他用户可以从知道它的工作中受益。 – DMason

回答

1

很多人会做,如果你正在改变PK值,则需要重新思考的说法数据库/表格设计。但是,如果您需要快速修复脏点错误,请在客户表中添加一个唯一(而非空)的列。使用此列可以在更新触发器中的[插入]和[删除]表之间进行连接。这里有一个示例脚本:

CREATE TABLE dbo.Customer (
    Id INT CONSTRAINT PK_Customer PRIMARY KEY, 
    Name VARCHAR(128), 
    UQColumn INT IDENTITY NOT NULL CONSTRAINT UQ_Customer_UQColumn UNIQUE 
) 

CREATE TABLE dbo.[Log] (
    CustomerId INT NOT NULL, 
    LogMsg VARCHAR(MAX) 
) 

INSERT INTO dbo.Customer 
    (Id, Name) 
VALUES 
    (1, 'Larry'), 
    (2, 'Curley'), 
    (3, 'Moe') 

INSERT INTO dbo.[Log] 
    (CustomerId, LogMsg) 
VALUES 
    (1, 'Larry is cool'), 
    (1, 'Larry rocks'), 
    (2, 'Curley cracks me up'), 
    (3, 'Moe is mean') 


CREATE TRIGGER [dbo].[tr_Customer_Upd] 
ON [dbo].[customer] 
FOR UPDATE 
AS 
BEGIN 

UPDATE l 
SET CustomerId = i.Id 
FROM inserted i 
JOIN deleted d 
    ON i.UQColumn = d.UQColumn 
JOIN [Log] l 
    ON l.CustomerId = d.Id 
END 

SELECT * 
FROM dbo.[Log] 

UPDATE dbo.Customer 
SET Id = 4 
WHERE Id = 1 

SELECT * 
FROM dbo.[Log] 
+0

我不清楚你为什么加入删除和插入时,我想执行只有当ID字段更新(未插入或删除) – user1287453

+0

@ user1287453此触发器:inserted和deleted表是由SQL Server自动为DML触发器创建的特殊表。这些表存在INSERT,UPDATE和DELETE。 http://technet.microsoft.com/en-us/library/ms191300.aspx – DMason

+0

@ user1287453:澄清,所述更新触发的范围内,[插入]表和[删除]表都包含该行受UPDATE语句的影响。 [删除]是“之前”,[插入]是“之后”。那有意义吗? – DMason