by JBrooks
18. September 2014 09:19
I create archive tables to log all of the changes made to a table. The archive tables look like the base table with a few columns added. Then the base tables need a triggers to insert the old row right before a change. I used the stored proc below to generate the archive tables and triggers. You need a schema called “archives” for this to work.
create proc CreateArchive(@tablename nvarchar(200), @schema nvarchar(200) = 'dbo')
as
begin
declare @sql nvarchar(4000)
set @sql = '
create table archives.'+@tablename+'Arc
([archiveId] [int] IDENTITY(1,1) NOT NULL,
[archiveAction] [char](1) NOT NULL,
[archiveBy] [varchar](128) NULL,
[archived] [datetime] NULL,
'
select @sql = @sql + '['+c.COLUMN_NAME+'] ' +
+ c.DATA_TYPE +
CASE WHEN c.CHARACTER_MAXIMUM_LENGTH > 0
THEN '('+ltrim(cast(c.CHARACTER_MAXIMUM_LENGTH as varchar(4)))+')'
WHEN c.CHARACTER_MAXIMUM_LENGTH = -1
THEN '(MAX)'
ELSE '' END +
' NULL,
'
from INFORMATION_SCHEMA.COLUMNS c
where TABLE_NAME = @tablename
and TABLE_SCHEMA = @schema
order by c.ORDINAL_POSITION
set @sql = @sql + 'CONSTRAINT [PK_'+ @tablename + 'Arc] PRIMARY KEY CLUSTERED
(
[archiveId] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
ALTER TABLE [archives].[' + @tablename + 'Arc]
ADD CONSTRAINT [DF_' + @tablename + 'Arc_archiveBy]
DEFAULT (user_name()) FOR [archiveBy];
ALTER TABLE [archives].[' + @tablename + 'Arc]
ADD CONSTRAINT [DF_' + @tablename + 'Arc_archived]
DEFAULT (getdate()) FOR [archived];
grant all on [archives].[' + @tablename + 'Arc] to public;'
print @sql
exec sp_executesql @sql
set @sql = '
Create trigger [' + @schema + '].[t' + @tablename + 'Arc]
on [' + @schema + '].[' + @tablename + ']
for update, delete
as
begin
set nocount on
declare @Action char(1)
if exists (select 1 from inserted)
set @Action = ''U''
else
set @Action = ''D''
insert into archives.[' + @tablename + 'Arc]
(archiveAction'
select @sql = @sql + ', ['+c.COLUMN_NAME+']'
from INFORMATION_SCHEMA.COLUMNS c
where TABLE_NAME = @tablename
order by c.ORDINAL_POSITION
set @sql = @sql + ')
select @Action'
select @sql = @sql + ', ['+c.COLUMN_NAME+']'
from INFORMATION_SCHEMA.COLUMNS c
where TABLE_NAME = @tablename
order by c.ORDINAL_POSITION
set @sql = @sql + '
from deleted
end;'
print @sql
exec sp_executesql @sql
end
go
Here are some of the scripts I used to help with this:
-- create the archives schema
create schema archives
-- Generate the commands that call the stored proc for each table:
select 'exec CreateArchive '+TABLE_NAME + ';'
from INFORMATION_SCHEMA.TABLES
where TABLE_SCHEMA = 'dbo'
order by TABLE_NAME
-- drop the tables if I got an error:
select 'drop table archives.'+TABLE_NAME + ';'
from INFORMATION_SCHEMA.TABLES
where TABLE_SCHEMA = 'archives'
order by TABLE_NAME
-- drop the triggers if I got an error:
select 'drop trigger '+name + ';'
from sys.triggers
where create_date > getdate() - 1
order by name
-- see what object were last changed in the database
select *
from sys.objects
order by modify_date desc
bee0e585-3a2a-480e-a0db-38f3cdb6ac5a|2|5.0|27604f05-86ad-47ef-9e05-950bb762570c
Tags: