我试图创建一个触发器来记录许多表中的任何更改。但现在,我只在一个名为" MAN_OS_TIPO"的表中进行测试。
我需要检测哪个列已被更改,并将OLD和NEW值放入日志表中" SYS_LOG_UPDATE"
PS:如果您知道另一种记录更新的方式,请告诉我
PS:此表将存储来自多个表的日志数据。
这是用于创建表的CODE:
USE [SIGO]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
DROP TABLE dbo.MAN_OS_TIPO -- Just for test faster
/* CREATE */
CREATE TABLE dbo.MAN_OS_TIPO (
Id int IDENTITY(1,1) NOT NULL,
Descricao nvarchar(30) NOT NULL,
/* System */
LData datetime NULL,
LUser int NULL,
CData datetime NOT NULL,
CUser int NULL
CONSTRAINT [PK_MAN_OS_TIPO] PRIMARY KEY NONCLUSTERED (
[Id] 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
/* DEFAULT */ ALTER TABLE dbo.MAN_OS_TIPO ADD CONSTRAINT DF_MAN_OS_TIPO_CDATA DEFAULT getdate() for [CData]
GO
/* UNIQUE */ ALTER TABLE dbo.MAN_OS_TIPO ADD CONSTRAINT UQ_MAN_OS_TIPO_DESCRICAO UNIQUE (Descricao)
GO
/* TRIGGER */
CREATE TRIGGER TR_MAN_OS_TIPO_UPDATE ON dbo.MAN_OS_TIPO
FOR UPDATE
AS
DECLARE
@OldValue nvarchar(max), -- Valor antigo
@NewValue nvarchar(max), -- Valor novo
@LUser int, -- Usuário que está alterando
@Id int, -- Id do registro
@qtd int, -- Quantity of column in table
@cont int, -- while Counter
@tab nvarchar(max), -- Name of table
@col nvarchar(max), -- Name of column
@sql nvarchar(max), -- SQL
SET @cont = 1
SET @tab = 'MAN_OS_TIPO'
-- Count how many columns the table has
SELECT @qtd = COUNT(*) FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME = @tab
WHILE (@cont <= @qtd)
BEGIN
SELECT @col = COLUMN_NAME FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME = @tab AND ORDINAL_POSITION = @cont
IF (@col != 'Id' AND @col != 'CUser' AND @col != 'CData' AND @col != 'LUser' AND @col != 'LData')
BEGIN
PRINT @col
-- Get old values
SELECT @Id = Id, @OldValue = CAST(convert(nvarchar,@col,103) AS NVARCHAR) FROM DELETED
-- Get new values
SELECT @NewValue = CAST(convert(nvarchar,' + @col + ',103) AS NVARCHAR), @LUser = LUser FROM INSERTED
PRINT 'old: ' + @OldValue + ' // new: ' + @NewValue -- Just for debug
IF (@NewValue != @OldValue) -- Just if the value was changed
BEGIN
-- Insert in the log table
INSERT INTO [dbo].[SYS_LOG_UPDATE] ([Tabela],[Coluna], [DadoAntigo],[DadoNovo],[Usuario],[Data])
VALUES (@tab,@col,@OldValue,@NewValue,@LUser,getdate())
PRINT 'LOG!' -- Just for debug
END
END
SET @cont = @cont + 1
END
SET @sql = 'UPDATE ' + @tab + ' SET [LData] = getdate() WHERE [Id] = ' + CAST(@Id AS nvarchar) -- Just inform the last update date
PRINT @sql
EXEC(@sql)
GO
此代码用于填充表格:
-- Insert new value
INSERT INTO [dbo].[MAN_OS_TIPO]
([Descricao]
,[CData]
,[CUser])
VALUES
('Corretiva',
getdate(),
1)
GO
-- Update value
UPDATE [dbo].[MAN_OS_TIPO]
SET [Descricao] = 'Corretiva A'
,[LUser] = 2
WHERE [Descricao] = 'Corretiva'
GO
当我试图获得旧价值时......
SELECT @Id = Id, @OldValue = CAST(convert(nvarchar,@col,103) AS NVARCHAR) FROM DELETED
... @OldValue收到列的名称。但我需要在列中获取值。
我可以手动指定列的所有名称,但这会留下非常大的代码。
顺便说一下......如果你知道如何获取列的值或在日志表中注册所有更新,我很高兴。