跟踪变化SQL服务器2005年数据库
-
08-07-2019 - |
题
我已经负责制定一个解决方案的轨道改变到一个数据库。
为更新我需要捕捉:
- 日期的更新
- 旧价值
- 新的价值
- 田受影响
- 人这样做改变
- 记录id
- 表记录在
对于删除:
- 日删除
- 人做删除
- 该头衔/说明/id的记录中删除。表我跟踪变化,在所有标题或说明的领域。我想捕捉到这个之前的记录被删除。
- 表记录在
对于插入:
- 插入日期
- 人这样做改变
- 记录id
- 表记录在
我已经想到了几种方法可以做到这一点:
- 我使用的存储程序的任何更新/删除/插入。我会创造一个通用的"跟踪"表。这将有足够的领域捕获的所有数据。我会再添加另一条线的每储存proc作的"插入记录进行跟踪表"。
- 缺点:所有的更新/删除/插入是所有的混乱在同一表格
- 许多领域归零
- 我怎么跟踪批次更新/删除/刀片?<-这可能不是一个问题。我真的不做任何事情这样在应用程序。
- 我怎么捕捉的用户做出更新。该数据库只是看到一个帐户。
- 编辑了很多现有的编码进行编辑。
- 最后,我可以创建一个触发器,被称为后更新/删除/插入。许多相同的缺点,作为第一个解决方案,除非:我需要编辑一样多的代码。我不知道我怎么会跟踪更新。它看起来并不像有一种方法使用的触发器看到最近更新的记录。
我使用asp.net,C#sql服务器2005年,iis6,windows2003年。我没有预算,所以可悲的是,我可以不购买任何东西来帮我这个。
谢谢你的答案!
解决方案
一个触发器就不会有你需要的所有信息一堆的原因-但是没有用户标识是硬道理。
我会说你是在正确的轨道上有一个共同的sp插入任何更改。如果你是标准化sp是你的接口,然后你未来的游戏-这将是难以偷偷在一个改变,是不是被跟踪。
看看这相当于审计跟踪的会计应用程序-这是日志的一个表中每一笔交易记录。他们不会实现独立刊物,用于存款、取款、调整等。这是同样的原则。
其他提示
我讨厌侧步的问题,我知道你有没有预算,但是最简单的解决方案将升级到SQL服务器2008年。它具有这个功能 建立在.我认为,至少应该提到的任何其他人遇到这个问题,甚至如果你不能使用它自己。
(其中可部署的版本SQL2008年,这个特点是只提供企业。)
我建议你使用2列在每一个表中。名称 rowhistory 和 在被删除 和数据类型将xml和位。永远不会删除该行,始终使用国旗在被删除 现在去更新的触发器。我会给你例,为相同的 我有这个表叫做页
CREATE TABLE te_Page([Id] [int] IDENTITY(1,1) NOT NULL, [Name] [varchar](200) NOT NULL, [Description] [varchar](200) NULL,[CreatedBy] [uniqueidentifier] NULL, [CreatedDate] [datetime] NOT NULL, [UpdatedBy] [uniqueidentifier] NULL, [UpdatedDate] [datetime] NULL, [IsDeleted] [bit] NULL, [RowHistory] [xml] NULL, CONSTRAINT [PK_tm_Page] PRIMARY KEY CLUSTERED ([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]
现在在创建之后的表格中的所有您需要做的是复制贴以下代码和你的任务是做为一页的表中。它将开始记录的历史上排在相同的行更新沿用旧的和新的价值观。
ALTER Trigger [dbo].[Trg_Te_Page]
On [dbo].[te_Page]
After Update
As
--If @@rowcount = 0 Or Update(RowHistory)
--Return
Declare @xml NVARCHAR(MAX)
Declare @currentxml NVARCHAR(MAX)
Declare @node NVARCHAR(MAX)
Declare @ishistoryexists XML
Declare @FormLineAttributeValueId int
-- new Values
Declare @new_Name varchar(200)
Declare @new_Description varchar(200)
Declare @new_CreatedBy UNIQUEIDENTIFIER
Declare @new_CreatedDate DATETIME
Declare @new_UpdatedBy UNIQUEIDENTIFIER
Declare @new_UpdatedDate DATETIME
Declare @new_IsDeleted BIT
--old values
Declare @old_Name varchar(200)
Declare @old_Description varchar(200)
Declare @old_CreatedBy UNIQUEIDENTIFIER
Declare @old_CreatedDate DATETIME
Declare @old_UpdatedBy UNIQUEIDENTIFIER
Declare @old_UpdatedDate DATETIME
Declare @old_IsDeleted BIT
-- declare temp fmId
Declare @fmId int
-- declare cursor
DECLARE curFormId cursor
FOR select Id from INSERTED
-- open cursor
OPEN curFormId
-- fetch row
FETCH NEXT FROM curFormId INTO @fmId
WHILE @@FETCH_STATUS = 0
BEGIN
Select
@FormLineAttributeValueId = Id,
@old_Name = Name,
@old_Description = [Description],
@old_CreatedBy = CreatedBy,
@old_CreatedDate =CreatedDate,
@old_UpdatedBy =UpdatedBy,
@old_UpdatedDate =UpdatedDate,
@old_IsDeleted = IsDeleted,
@currentxml = cast(RowHistory as NVARCHAR(MAX))
From DELETED where Id=@fmId
Select
@new_Name = Name,
@new_Description = [Description],
@new_CreatedBy = CreatedBy,
@new_CreatedDate =CreatedDate,
@new_UpdatedBy =UpdatedBy,
@new_UpdatedDate =UpdatedDate,
@new_IsDeleted = IsDeleted
From INSERTED where Id=@fmId
set @old_Name = Replace(@old_Name,'&','&')
set @old_Name = Replace(@old_Name,'>','>')
set @old_Name = Replace(@old_Name,'<','<')
set @old_Name = Replace(@old_Name,'"','"')
set @old_Name = Replace(@old_Name,'''',''')
set @new_Name = Replace(@new_Name,'&','&')
set @new_Name = Replace(@new_Name,'>','>')
set @new_Name = Replace(@new_Name,'<','<')
set @new_Name = Replace(@new_Name,'"','"')
set @new_Name = Replace(@new_Name,'''',''')
set @old_Description = Replace(@old_Description,'&','&')
set @old_Description = Replace(@old_Description,'>','>')
set @old_Description = Replace(@old_Description,'<','<')
set @old_Description = Replace(@old_Description,'"','"')
set @old_Description = Replace(@old_Description,'''',''')
set @new_Description = Replace(@new_Description,'&','&')
set @new_Description = Replace(@new_Description,'>','>')
set @new_Description = Replace(@new_Description,'<','<')
set @new_Description = Replace(@new_Description,'"','"')
set @new_Description = Replace(@new_Description,'''',''')
set @xml = ''
BEGIN
-- for Name
If ltrim(rtrim(IsNull(@new_Name,''))) != ltrim(rtrim(IsNull(@old_Name,'')))
set @xml = @xml + '<ColumnInfo ColumnName="Name" OldValue="'+ @old_Name + '" NewValue="' + @new_Name + '"/>'
-- for Description
If ltrim(rtrim(IsNull(@new_Description,''))) != ltrim(rtrim(IsNull(@old_Description,'')))
set @xml = @xml + '<ColumnInfo ColumnName="Description" OldValue="'+ @old_Description + '" NewValue="' + @new_Description + '"/>'
-- CreatedDate
If IsNull(@new_CreatedDate,'') != IsNull(@old_CreatedDate,'')
set @xml = @xml + '<ColumnInfo ColumnName="CreatedDate" OldValue="'+ cast(isnull(@old_CreatedDate,'') as varchar(100)) + '" NewValue="' + cast(isnull(@new_CreatedDate,'') as varchar(100)) + '"/>'
-- CreatedBy
If cast(IsNull(@new_CreatedBy,'00000000-0000-0000-0000-000000000000')as varchar (36)) != cast(IsNull(@old_CreatedBy,'00000000-0000-0000-0000-000000000000')as varchar(36))
set @xml = @xml + '<ColumnInfo ColumnName="CreatedBy" OldValue="'+ cast(IsNull(@old_CreatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) + '" NewValue="' + cast(isnull(@new_CreatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))+
'"/>'
-- UpdatedDate
If IsNull(@new_UpdatedDate,'') != IsNull(@old_UpdatedDate,'')
set @xml = @xml + '<ColumnInfo ColumnName="UpdatedDate" OldValue="'+ cast(IsNull(@old_UpdatedDate,'') as varchar(100)) + '" NewValue="' + cast(IsNull(@new_UpdatedDate,'') as varchar(100)) + '"/>'
-- UpdatedBy
If cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) != cast(IsNull(@old_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))
set @xml = @xml + '<ColumnInfo ColumnName="UpdatedBy" OldValue="'+ cast(IsNull(@old_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) + '" NewValue="' + cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))+
'"/>'
-- IsDeleted
If cast(IsNull(@new_IsDeleted,'') as varchar(10)) != cast(IsNull(@old_IsDeleted,'') as varchar(10))
set @xml = @xml + '<ColumnInfo ColumnName="IsDeleted" OldValue="'+ cast(IsNull(@old_IsDeleted,'') as varchar(10)) + '" NewValue="' + cast(IsNull(@new_IsDeleted,'') as varchar(10)) + '" />'
END
Set @xml = '<RowInfo TableName="te_Page" UpdatedBy="' + cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(50)) + '" UpdatedDate="' + Convert(Varchar(20),GetDate()) + '">' + @xml + '</RowInfo>'
Select @ishistoryexists = RowHistory From DELETED
--print @ishistoryexists
If @ishistoryexists is null
Begin
Set @xml = '<History>' + @xml + '</History>'
Update te_Page
Set
RowHistory = @xml
Where
Id = @FormLineAttributeValueId
End
Else
Begin
set @xml = REPLACE(@currentxml, '<History>', '<History>' + @xml)
Update te_Page
Set
RowHistory = @xml
Where
Id = @FormLineAttributeValueId
End
FETCH NEXT FROM curFormId INTO @fmId
END
CLOSE curFormId
DEALLOCATE curFormId
现在,只要你将执行任何更新的数据将被存储在 rowhistory 柱
一个我已经看到这种处理了(虽然我不建议,说实话)是处理它经由存储程序,通过在userid/username/无论作为一个参数。存储程序将电话记录的程序,其中写道:有关细节在一个中央记录表。
这里是哪里有点古怪,但...
插入/更新的有关行(s)存在表中作为XML数据,一旦插入/更新已经成功完成。对于删除,行之前贮存的删除运行(不过,实际上,他们可能已经得到了它从中删除发言的输出--至少与SQL服务器2005年)。
如果我正确地记得,该表仅有几个列:UserID,DateTime的记录,交易类型(I/U/D)、XML数据含有关排,表名称和主键值(主要用于快速搜索什么样的记录他们想要的).
许多方面为一只猫的皮肤,但...
我的建议是保持简单。它扩大了后来如果您需要。
如果你有能力这样做,锁定用户只能够执行可操作的发言表通过存储的过程和后处理的记录(但是你想要的)。
我们建立我们自己的,只是需要用户和电脑传递给每个加入/更新存储的过程。那么它只是一个问题,得到原始记录adn填充的变量,并比较它们的通过变量和记录的数据对我们表。删除我们只有一份发表+时间戳场所的记录是从来没有真正被删除,可恢复的任何时候我们需要(显然是删除例行检查FK关系和诸).
加入/更新记录表看起来像 datetime, table_name, column_name, record_id, old_value, 新值, user_id, 计算机
我们永远不会插入空,以便我们将它们转化为空串,新的条目标有'{新项}'在old_value列。record_id是由作为许多关键列为唯一标识的这一个单独的记录(field1+'.' +field2+...)
首先,在所有的你的表格你至少应该有这些列入该数据列DateCreated,UserCreated,DateModified,UserModified.可能你可能需要添加一"地位"或"LastAction"栏所以,你永远不实际上删除一排,你只需要设置这一删除,插入/更新的状态。接下来,您可以创建一个"历史表",这是一个精确复制的第一个表格中。然后上任何更新或删除具有触发副本的已删除的表格进入历史表改变DateModified,UserModified和地位领域同时进行。
我有一个建立在SQL服务器在这里我们会使用的风景来访问我们的数据,这将把手插入、修改和删除而不是触发器。
例如:一个 而不是删除 扳机上的图将标志的记录的基础表中删除,并过滤以不显示删除的记录。
在所有的触发器,我们更新修改日期和用户名。麻烦的是记录数据库用户的名称,这是不一样的,因为最终的应用程序的用户名。
视需要架构开这个工作。
关于记录用户的变化DB:你可以创建多SQL用户需要对数据库以及如果您使用的会议和限制/注册的访问您的节目/脚本 你可以使用这些信息,以启动不同的数据库连接设置(即username), 之前的任何操作数据库。
至少,应该是可行的PHP-明智的脚本,但是我可能是错误的asp.net.