我不知道这些要求是否标准,但我想知道是否有解决办法可以做到以下几点:
我宁愿不必为每个表编写代码。我想知道是否有一个可以安装在SQL Server之上的解决方案,它会为你做这个吗?
答案 0 :(得分:35)
有很多方法可以做到这一点;它取决于您使用的SQL Server版本。
这里有一些
使用影子表和触发器审核跟踪 Here is the link
您也可以考虑使用SQL Server 2008审核功能 Here is the link
答案 1 :(得分:7)
我创建触发器,以XML方式执行此操作,我们可以将所有表记录到同一个表中,使其更灵活
CREATE TABLE [dbo].[AuditAll] (
AuditId int NOT NULL IDENTITY(1,1),
[DateTime] datetime NOT NULL,
TableName nvarchar(255) NOT NULL,
AuditEntry xml NULL,
CONSTRAINT [PK_AuditAll] PRIMARY KEY CLUSTERED ( AuditId ASC )
)
我只需要'旧'值,所以我只存储删除的表,无论如何都可以在表中看到插入的表。
CREATE TRIGGER AuditSimple
ON Simple
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF (SELECT COUNT(*) FROM deleted) > 0
begin
Declare @AuditMessage XML
--set valut to all xml from deleted table
set @AuditMessage = (select * from deleted for xml auto)
insert into AuditAll( DateTime, TableName, AuditEntry )
values ( GetDate(), 'Simple', @AuditMessage )
end
END
GO
我想这可以很容易地在sp_foreach中调用,为数据库中的每个表创建它,但我们现在不需要它,只记得更改你的表名
欢呼声
答案 2 :(得分:5)
您可以尝试基于第三方点击触发器的解决方案,例如ApexSQL Audit - SQL Server数据库的审核工具,它捕获数据库中发生的数据更改,包括有关谁制作的信息更改,对象受影响的时间,以及用于进行更改的SQL登录,应用程序和主机的信息。它将所有捕获的信息存储在中央存储库中,并以打印友好格式导出它们
免责声明:我在ApexSQL担任产品支持工程师
答案 3 :(得分:2)
由于这是许多企业应用程序中非常普遍的要求,因此以下解决方案基于我在博客上撰写的this article。
假设我们有一个Book
表,其审核日志信息必须存储在BookAuditLog
表中,如以下类图所示:
BookAuditLog
表的创建方式如下:
CREATE TABLE BookAuditLog (
BookId bigint NOT NULL,
OldRowData nvarchar(1000) CHECK(ISJSON(OldRowData) = 1),
NewRowData nvarchar(1000) CHECK(ISJSON(NewRowData) = 1),
DmlType varchar(10) NOT NULL CHECK (DmlType IN ('INSERT', 'UPDATE', 'DELETE')),
DmlTimestamp datetime NOT NULL,
DmlCreatedBy varchar(255) NOT NULL,
TrxTimestamp datetime NOT NULL,
PRIMARY KEY (BookId, DmlType, DmlTimestamp)
)
BookAuditLog
表列存储以下数据:
BookId
列存储为此日志事件创建的关联的Book
行的标识符。OldRowData
在执行INSERT,UPDATE或DELETE语句之前存储Book
记录状态的JSON表示形式。NewRowData
存储Book
记录状态的JSON表示形式。DmlType
是一个枚举列,存储创建,更新或删除给定Book
行的DML语句类型。DmlTimestamp
存储DML语句执行时间戳。DmlCreatedBy
存储发出INSERT,UPDATE或DELETE DML语句的用户。TrxTimestamp
存储更改了Book
记录的事务的时间戳。要捕获INSERT,UPDATE和DELETE DML语句,我们需要创建三个数据库触发器,这些触发器将在BookAuditLog
表中插入记录。
要拦截Book
表上的INSERT语句,我们将创建TR_Book_Insert_AuditLog
触发器:
CREATE TRIGGER TR_Book_Insert_AuditLog ON Book
FOR INSERT AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Inserted),
null,
(SELECT * FROM Inserted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
'INSERT',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
要捕获Book
记录上的UPDATE语句,我们将创建以下TR_Book_Update_AuditLog
触发器:
CREATE TRIGGER TR_Book_Update_AuditLog ON Book
FOR UPDATE AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Inserted),
(SELECT * FROM Deleted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
(SELECT * FROM Inserted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
'UPDATE',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
要拦截Book
表行上的DELETE语句,我们将创建以下TR_Book_Delete_AuditLog
触发器:
CREATE TRIGGER TR_Book_Delete_AuditLog ON Book
FOR DELETE AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Deleted),
(SELECT * FROM Deleted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
null,
'DELETE',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
在Book
表上执行INSERT语句时:
INSERT INTO Book (
Author,
PriceInCents,
Publisher,
Title,
Id
)
VALUES (
'Vlad Mihalcea',
3990,
'Amazon',
'High-Performance Java Persistence 1st edition',
1
)
我们可以看到BookAuditLog
中插入了一条记录,该记录捕获了刚刚在Book
表上执行的INSERT语句:
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
在更新Book
表行时:
UPDATE Book
SET PriceInCents = 4499
WHERE Id = 1
我们可以看到BookAuditLog
表上的AFTER UPDATE触发器将新记录添加到Book
:
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | UPDATE | 2020-11-08 08:43:22.803 | Vlad Mihalcea | 2020-11-08 06:43:22.807 |
删除Book
表行时:
DELETE FROM Book
WHERE Id = 1
通过BookAuditLog
表上的AFTER DELETE触发器将新记录添加到Book
:
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | UPDATE | 2020-11-08 08:43:22.803 | Vlad Mihalcea | 2020-11-08 06:43:22.807 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | | DELETE | 2020-11-08 08:44:25.630 | Vlad Mihalcea | 2020-11-08 06:44:25.633 |
答案 4 :(得分:0)
看看触发器。这些可用于实现符合您要求的东西。
答案 5 :(得分:0)
看一下这篇文章 - Auditing in SQL Server 2008,它精美地利用了SQL Server 2008中已经存在的审计功能。
我还必须提到@Microtechie回答了一些很棒的文章。阅读它们并确定哪一个更容易适应。
答案 6 :(得分:0)
我看到3种方法来实现这一目标:
使用选项'2',万一出现任何问题,您可以关闭复制/日志传送,并获得几秒钟的精确数据备份。 例如,如果使用选项“ 3”,则每5分钟具有不同的备份频率,那么,如果出现任何问题,您可以恢复5分钟之久的正确数据副本。
答案 7 :(得分:-2)
使用数据库快照,您可以在该瞬间保留数据的只读副本。此外,通过备份日志,您可以在特定时间段恢复信息。
您还可以从日志中读取信息以检索更改的信息。
您不喜欢的另一个解决方案是使用触发器跟踪更改,但可能需要处理每个表。您还可以启用“更改数据捕获”功能来检测更改,还需要为每个表启用此功能,但它需要的代码少于触发器。
最后,还有第三方工具,例如Apex SQL Trigger,只需点击几下,配置就会自动完成这项工作。