我正在编写一个触发器,用于为一张表的插入和更新记录保留审计记录。
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
LEFT JOIN INSERTED i ON pv.Personid = i.Personid
LEFT JOIN DELETED d ON pv.Personid = d.Personid;
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
最后一次插入失败,因为它试图将null插入applog表中的recordid列,有人可以解释或解决此问题。
答案 0 :(得分:0)
失败的语句如下:
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
这是因为在触发器中,您使用Persons
是您的“基本”表,并且对LEFT JOIN
和inserted
都执行了deleted
。结果,当您尝试执行上述INSERT
时,触发器的数据集中也会使用前一个INSERT
的值。第二个人'Parida'
中没有人inserted
出现在表INSERT
中,因此COALESCE(i.Personid,NULL)
返回NULL
;正如我在评论中提到的那样,使用COALESCE
返回NULL
毫无意义,就好像一个表达式的值求值为NULL
时它将返回NULL
。由于RecordID
(正在插入COALESCE(i.Personid,NULL)
的值)不能具有值NULL
,因此INSERT
将失败,整个交易将回滚。
我怀疑您想要的触发器如下:
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS BEGIN
INSERT INTO AppLog (TableName,
ColumnName,
RecordId,
OldValue,
NewValue,
UpdatedBy,
UpdatedOn)
SELECT 'Persons',
'LastName',
i.Personid,
d.LastName,
i.LastName,
CURRENT_USER,
GETDATE()
FROM inserted AS i
LEFT JOIN deleted AS d ON i.Personid = d.Personid;
END;
inserted
对于UPDATE
或INSERT
总是至少有1行。 inserted
不能用于DELETE
,但是您的触发器不会在该DML事件上触发,因此使用inserted
作为“基本”表似乎是正确的选择。
答案 1 :(得分:0)
以下代码应该可以工作
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
If exists (Select * from inserted) and not exists(Select * from deleted)
begin
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT
'Persons', 'LastName',i.Personid,NULL,i.LastName,CURRENT_USER,GETDATE()
FROM
inserted AS i
END
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('abc','def',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('gg','hh',90);
UPDATE dbo.Persons SET LastName='Paridachanged' WHERE Personid=1
SELECT * FROM Persons
SELECT * FROM AppLog
答案 2 :(得分:0)
USE KnockKnockDev;
GO
IF OBJECT_ID('dbo.AuditRecord', 'TR') IS NOT NULL
DROP TRIGGER dbo.AuditRecord;
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT, DELETE
AS
DECLARE @Action as char(1)
DECLARE @Count as int
DECLARE @TableName as char(32)
DECLARE @ColumnName as char (32)
SET @TableName = 'Persons'
SET @ColumnName = 'LastName'
SET @Action = 'I' -- Set Action to 'I'nsert by default.
SELECT @Count = COUNT(*) FROM DELETED
IF @Count > 0
BEGIN
SELECT @Count = COUNT(*) FROM INSERTED
IF @Count > 0
SET @Action = 'U' -- Set Action to 'U'pdated.
ELSE
SET @Action = 'D' -- Set Action to 'D'eleted.
END
IF @Action = 'I'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT @TableName, @ColumnName, Personid,
NULL, LastName, @Action, CURRENT_USER, GETDATE()
FROM INSERTED;
END
ELSE IF @Action = 'D'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT @TableName, @ColumnName, Personid,
LastName, NULL, @Action, CURRENT_USER, GETDATE()
FROM DELETED;
END
ELSE
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT @TableName, @ColumnName, i.Personid,
d.LastName, i.LastName, @Action, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
GO