【问题标题】:SQL Server Changelog creation, Identity Syntax, and Invalid COlumnsSQL Server 变更日志创建、标识语法和无效列
【发布时间】:2013-02-19 00:08:02
【问题描述】:

我目前正在创建一个 SQL Server 触发器,该触发器在更新后应该填充一个更改日志,其中包含所做的任何薪水更改以及由哪个用户更改。

我制作的更新日志表可以在这里看到:

CREATE TABLE ChangeLog
(
ChangeID int identity(1,1) primary key,
EmpID int,
[User] nvarchar(30),
[Date] smalldatetime,
OldRate money,
NewRate money
)

据我所知,表的一切都很好,但是当我去创建触发器时,我开始收到一些错误(以及一大堆混乱。)我已经尝试研究几种方法一个用新行更新不同表的触发器,据我所知,它的结构是正确的,但是我不确定我是如何弄乱内容的。

CREATE TRIGGER payrate_change ON Employees FOR UPDATE
As
DECLARE @originalPay VARCHAR(100)
DECLARE @newPay VARCHAR(100)
If UPDATE (PayRate)
BEGIN
SELECT @originalPay = (SELECT PayRate FROM deleted)
SELECT @newPay = (SELECT PayRate FROM inserted)
INSERT INTO [dbo].[ChangeLog]
        (ChangeID, EmpID, [User], [Date], OldRate, NewRate)
    VALUES
        identity(1,1), 
        Employees.EmployeeID, 
        SUSER_SNAME(), 
        SYSDATETIME(), 
        @originalPay, 
        @newPay
    FROM inserted
END

两个 select 语句的 payrate 部分给出了一个错误,指出它们是无效的列,即使它上面的两行调用 PayRate 就好了。然后对于 Insert Into 语句的值部分,identity 声称语法不正确,尽管我在创建表时以完全相同的方式使用它。

有人对此触发器可能存在什么问题有任何想法吗?任何意见将不胜感激。

编辑:

在下面建议的更改之后,我将 ChangeID(主键)重新添加到触发器中,但是现在 IDENTITY 给了我一个不正确的语法错误:

CREATE TRIGGER payrate_change ON Employees FOR UPDATE
As

If UPDATE (PayRate)
BEGIN

INSERT INTO [dbo].[ChangeLog]
        (ChangeID, EmpID, [User], [Date], OldRate, NewRate)
    select
        IDENTITY(1,1),
        i.EmployeeID, 
        SUSER_SNAME(), 
        SYSDATETIME(), 
        d.PayRate, 
        i.PayRate
    FROM inserted i
    JOIN deleted d on i.EmployeeID = d.deleted
END

EDIT2:为感兴趣的人添加最终结果:

CREATE TRIGGER payrate_change2 ON Employees FOR UPDATE
AS

If UPDATE (Pay)
BEGIN

INSERT INTO [dbo].[ChangeLog]
        (EmpID, [User], [Date], OldRate, NewRate)
    select
        i.EmployeeID, 
        SUSER_SNAME(), 
        SYSDATETIME(), 
        d.Pay, 
        i.Pay
    FROM inserted i
    JOIN deleted d on i.EmployeeID = d.EmployeeID
END

【问题讨论】:

    标签: sql sql-server tsql database-design triggers


    【解决方案1】:

    省略标识列,它将自行填充

    您的触发器无法处理多行更新,请查看 Best Practice: Coding SQL Server triggers for multi-row operations

    你可以JOIN删除和插入伪表,我假设EmployeeID是关键?

    试试这个

    CREATE TRIGGER payrate_change ON Employees FOR UPDATE
    As
    
    If UPDATE (PayRate)
    BEGIN
    
    INSERT INTO [dbo].[ChangeLog]
            (EmpID, [User], [Date], OldRate, NewRate)
        select
            i.EmployeeID, 
            SUSER_SNAME(), 
            SYSDATETIME(), 
            d.PayRate, 
            i.PayRate
        FROM inserted i
        JOIN deleted d on i.EmployeeID = d.deleted
    END
    

    还要注意If UPDATE (PayRate) 会触发,即使您执行SET PayRate = PayRate 之类的操作所以您可能想检查该值是否实际已更改,您可以在插入和删除之间的 JOIN 中添加它,并确保检查NULLS

    【讨论】:

    • 实际上 ChangeID 是我想要的主键,因为这将更新可能有多个相同员工 ID 的变更日志。之后我尝试添加 ChangeID,因为 PayRate 仍然抛出“无效列”错误,并且我想出了我现在添加到原始帖子中的内容。我是否以某种方式错误地做身份声明?我认为这是正确执行此操作的方法,但似乎仍然会抛出错误,说明语法不正确。
    • ChangeID 将自动生成,因为它是一个标识列..省略它
    • 好的,感谢您的快速回复。您知道为什么 PayRate 和 deleted 仍显示为无效的列名吗?它显示的错误是:“Msg 207, Level 16, State 1, Procedure payrate_change, Line 4 Invalid column name 'PayRate'. Msg 207, Level 16, State 1, Procedure payrate_change, Line 16 Invalid column name 'deleted'。消息207, Level 16, State 1, Procedure payrate_change, Line 13 Invalid column name 'PayRate'. Msg 207, Level 16, State 1, Procedure payrate_change, Line 14 Invalid column name 'PayRate'. "
    • Employees 表是否有 PayRate 列?
    • 我进行了仔细检查,我显然将其称为 Pay 而不是 PayRate。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多