gpt4 book ai didi

sql - 如何在SQL Server中的历史表中存储历史记录

转载 作者:行者123 更新时间:2023-12-01 22:13:09 27 4
gpt4 key购买 nike

我有 2 个表,Table-ATable-A-History

  • Table-A 包含当前数据行。
  • Table-A-History 包含历史数据

我希望在 Table-A 中包含最新的数据行,并且 Table-A-History 包含历史行。

我可以想到两种方法来实现这一目标:

  1. 每当有新数据行可用时,将当前行从Table-A移动到Table-A-History并更新Table-包含最新数据的 行(通过 insert into selectselect into table)

  2. 只要有新的数据行可用,就更新Table-A 的行并将新行插入到Table-A-History 中。

就性能而言,方法 1 还是方法 2 更好?有更好的不同方法来实现这一点吗?

最佳答案

基本上,您希望跟踪/审核对表的更改,同时保持主表的大小较小。

有多种方法可以解决此问题。下面讨论每种方式的优缺点。

1 - 使用触发器审核表。

如果您希望审核表(插入、更新、删除),请查看我的如何阻止不需要的事务 - SQL Saturday 幻灯片,带代码 - http://craftydba.com/?page_id=880 。填充审核表的触发器可以保存来自多个表的信息(如果您选择),因为数据保存为 XML。因此,如有必要,您可以通过解析 XML 来取消删除操作。它跟踪谁以及什么进行了更改。

(可选)您可以将审核表放在其自己的文件组中。

Description:
Table Triggers For (Insert, Update, Delete)
Active table has current records.
Audit (history) table for non-active records.

Pros:
Active table has smaller # of records.
Index in active table is small.
Change is quickly reported in audit table.
Tells you what change was made (ins, del, upd)

Cons:
Have to join two tables to do historical reporting.
Does not track schema changes.

2 - 记录的有效日期

如果您永远不会从审核表中清除数据,为什么不将该行标记为已删除,而是永远保留它呢?许多系统(例如人员软件)使用有效的约会来显示记录是否不再有效。在 BI 世界中,这称为 2 维表(缓慢变化的维度)。请参阅数据仓库研究所文章。 http://www.bidw.org/datawarehousing/scd-type-2/每条记录都有开始日期和结束日期。

所有事件记录的结束日期均为空。

Description:
Table Triggers For (Insert, Update, Delete)
Main table has both active and historical records.

Pros:
Historical reporting is easy.
Change is quickly shown in main table.

Cons:
Main table has a large # of records.
Index of main table is large.
Both active & history records in same filegroup.
Does not tell you what change was made (ins, del, upd)
Does not track schema changes.

3 - 更改数据捕获(企业功能)。

Microsoft SQL Server 2008 引入了变更数据捕获功能。虽然这会在事后使用 LOG 读取器跟踪数据更改 (CDC),它缺乏诸如谁以及什么做出了改变之类的信息。 MSDN 详细信息 - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

此解决方案依赖于正在运行的 CDC 作业。 sql 代理的任何问题都会导致数据显示延迟。

查看变更数据捕获表。 http://technet.microsoft.com/en-us/library/bb500353(v=sql.105).aspx

Description:
Enable change data capture

Pros:
Do not need to add triggers or tables to capture data.
Tells you what change was made (ins, del, upd) the _$operation field in
<user_defined_table_CT>
Tracks schema changes.

Cons:
Only available in enterprise version.
Since it reads the log after the fact, time delay in data showing up.
The CDC tables do not track who or what made the change.
Disabling CDC removes the tables (not nice)!
Need to decode and use the _$update_mask to figure out what columns changed.

4 - 更改跟踪功能(所有版本)。

Microsoft SQL Server 2008 引入了更改跟踪功能。与 CDC 不同,它附带所有版本;然而,它附带了一堆 TSQL 函数,您必须调用它们才能弄清楚发生了什么。

它的设计目的是通过应用程序将一个数据源与 SQL Server 同步。 TechNet 上有完整的同步框架。

http://msdn.microsoft.com/en-us/library/bb933874.aspx http://msdn.microsoft.com/en-us/library/bb933994.aspx http://technet.microsoft.com/en-us/library/bb934145(v=sql.105).aspx

与 CDC 不同,您可以指定更改在被清除之前在数据库中持续的时间。另外,插入和删除不记录数据。更新仅记录更改的字段。

由于您要将 SQL Server 源同步到另一个目标,因此效果很好。除非您编写定期作业来找出更改,否则这对审计不利。

您仍然需要将该信息存储在某处。

Description:
Enable change tracking

Cons:
Not a good auditing solution

前三个解决方案适用于您的审核。我喜欢第一个解决方案,因为我在我的环境中广泛使用它。

真诚的

约翰

演示文稿中的代码片段(汽车数据库)

-- 
-- 7 - Auditing data changes (table for DML trigger)
--


-- Delete existing table
IF OBJECT_ID('[AUDIT].[LOG_TABLE_CHANGES]') IS NOT NULL
DROP TABLE [AUDIT].[LOG_TABLE_CHANGES]
GO


-- Add the table
CREATE TABLE [AUDIT].[LOG_TABLE_CHANGES]
(
[CHG_ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
[CHG_DATE] [datetime] NOT NULL,
[CHG_TYPE] [varchar](20) NOT NULL,
[CHG_BY] [nvarchar](256) NOT NULL,
[APP_NAME] [nvarchar](128) NOT NULL,
[HOST_NAME] [nvarchar](128) NOT NULL,
[SCHEMA_NAME] [sysname] NOT NULL,
[OBJECT_NAME] [sysname] NOT NULL,
[XML_RECSET] [xml] NULL,
CONSTRAINT [PK_LTC_CHG_ID] PRIMARY KEY CLUSTERED ([CHG_ID] ASC)
) ON [PRIMARY]
GO

-- Add defaults for key information
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_DATE] DEFAULT (getdate()) FOR [CHG_DATE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_TYPE] DEFAULT ('') FOR [CHG_TYPE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_BY] DEFAULT (coalesce(suser_sname(),'?')) FOR [CHG_BY];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_APP_NAME] DEFAULT (coalesce(app_name(),'?')) FOR [APP_NAME];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_HOST_NAME] DEFAULT (coalesce(host_name(),'?')) FOR [HOST_NAME];
GO



--
-- 8 - Make DML trigger to capture changes
--


-- Delete existing trigger
IF OBJECT_ID('[ACTIVE].[TRG_FLUID_DATA]') IS NOT NULL
DROP TRIGGER [ACTIVE].[TRG_FLUID_DATA]
GO

-- Add trigger to log all changes
CREATE TRIGGER [ACTIVE].[TRG_FLUID_DATA] ON [ACTIVE].[CARS_BY_COUNTRY]
FOR INSERT, UPDATE, DELETE AS
BEGIN

-- Detect inserts
IF EXISTS (select * from inserted) AND NOT EXISTS (select * from deleted)
BEGIN
INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
SELECT 'INSERT', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM inserted as Record for xml auto, elements , root('RecordSet'), type)
RETURN;
END

-- Detect deletes
IF EXISTS (select * from deleted) AND NOT EXISTS (select * from inserted)
BEGIN
INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
SELECT 'DELETE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
RETURN;
END

-- Update inserts
IF EXISTS (select * from inserted) AND EXISTS (select * from deleted)
BEGIN
INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
SELECT 'UPDATE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
RETURN;
END

END;
GO



--
-- 9 - Test DML trigger by updating, deleting and inserting data
--

-- Execute an update
UPDATE [ACTIVE].[CARS_BY_COUNTRY]
SET COUNTRY_NAME = 'Czech Republic'
WHERE COUNTRY_ID = 8
GO

-- Remove all data
DELETE FROM [ACTIVE].[CARS_BY_COUNTRY];
GO

-- Execute the load
EXECUTE [ACTIVE].[USP_LOAD_CARS_BY_COUNTRY];
GO

-- Show the audit trail
SELECT * FROM [AUDIT].[LOG_TABLE_CHANGES]
GO

-- Disable the trigger
ALTER TABLE [ACTIVE].[CARS_BY_COUNTRY] DISABLE TRIGGER [TRG_FLUID_DATA];

** 审计表的外观和感觉 **

enter image description here

关于sql - 如何在SQL Server中的历史表中存储历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11890868/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com