1

我有以下 SQL Server 表:

CREATE TABLE [dbo].[Logins](
    [LoginID] [int] IDENTITY(1,1) NOT NULL,
    [AbonnementID] [int] NOT NULL,
    [Zeitpunkt] [datetime] NULL,
    [IPAdresse] [nvarchar](255) NULL,
    [IstLogout] [bit] NULL,
 CONSTRAINT [PK_Logins] PRIMARY KEY CLUSTERED 
(
[LoginID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     
ALLOW_ROW_LOCKS      =     ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Logins]  WITH CHECK ADD  CONSTRAINT [FK_Logins_Abonnements] FOREIGN([AbonnementID])
REFERENCES [dbo].[Abonnements] ([AbonnementID])
GO

ALTER TABLE [dbo].[Logins] CHECK CONSTRAINT [FK_Logins_Abonnements]
GO

因此,我创建了一个触发器来写入 ChangeLog:

CREATE TRIGGER [dbo].[LoginsChangeLog]
ON [dbo].[Logins]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    DECLARE @LoginID INT
    DECLARE @TypID INT

    SET @TypID = (SELECT ChangeLogTables.ChangeLogTableID FROM ChangeLogTables WHERE ChangeLogTable = 'Logins')
    IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT inserted.LoginID FROM inserted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,1, @LoginID)
    END

    IF EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT inserted.LoginID FROM inserted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,2, @LoginID)
    END

    IF NOT EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT deleted.LoginID FROM deleted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,3, @LoginID)
    END
END

向表中添加行没问题,触发器成功完成,但是当我尝试使用 Nhibernate-Framework 删除表时出现异常:

无法执行更新查询 [SQL: 从登录中删除 AbonnementID=? 和时代朋克

这是我的 C# 代码:

    public void Cleanup(long Id, DateTime time)
    {
        var hqlBuilder = new StringBuilder();

        hqlBuilder.Append("DELETE Login AS login");
        hqlBuilder.Append(" WHERE login.Abonnement.AbonnementId = :Id");
        hqlBuilder.Append(" AND login.Zeitpunkt < :time ");


        CurrentSession.CreateQuery(hqlBuilder.ToString())
            .SetParameter("Id", Id)
            .SetParameter("time", time)
            .ExecuteUpdate();

    }

如果我删除我的触发器一切正常,但触发器必须完成他的工作并写入我的变更日志表

4

1 回答 1

1

您的触发器已损坏,因为它假定inserted并且deleted仅包含一行。实际上,它们可能包含 0、1 或多行。您需要编写一个触发器来处理所有这些可能性。就像是:

INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey)
SELECT clt.ChangeLogTableID,
   CASE WHEN i.LoginID is not null and d.LoginID is not null THEN 2
        WHEN i.LoginID is not null THEN 1
        ELSE 3 END,
   COALESCE(i.LoginID,d.LoginID)
FROM
   ChangeLogTables clt
      cross join
   (inserted i
      full outer join
   deleted d
      on
         i.LoginID = d.LoginID)
WHERE
   clt.ChangeLogTable = 'Logins'

应该更换整个触发器体。

于 2013-08-01T10:27:07.760 回答