Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 不使用触发器创建历史记录表_Sql Server_Tsql - Fatal编程技术网

Sql server 不使用触发器创建历史记录表

Sql server 不使用触发器创建历史记录表,sql-server,tsql,Sql Server,Tsql,我有一个表a,有3000条记录,有25列。我希望有一个名为table a history的历史记录表,其中包含所有的更改、更新和删除,以便我随时查找。我通常使用光标。现在我想使用触发器,但我没有被要求这么做。你还有其他建议吗?非常感谢 如果您使用的是tsql/SQL server,而无法使用触发器(这是获取每次更改的唯一可靠方法),则可以使用在作业中计划的存储过程每隔x个时间运行一次,该存储过程使用合并语句和两个表来获取新记录或更改。如果你毫无疑问需要每一个变化,我不会建议你这样做 CREATE

我有一个表a,有3000条记录,有25列。我希望有一个名为table a history的历史记录表,其中包含所有的更改、更新和删除,以便我随时查找。我通常使用光标。现在我想使用触发器,但我没有被要求这么做。你还有其他建议吗?非常感谢

如果您使用的是tsql/SQL server,而无法使用触发器(这是获取每次更改的唯一可靠方法),则可以使用在作业中计划的存储过程每隔x个时间运行一次,该存储过程使用合并语句和两个表来获取新记录或更改。如果你毫无疑问需要每一个变化,我不会建议你这样做

CREATE TABLE dbo.TableA (id INT, Column1 nvarchar(30))
CREATE TABLE dbo.TableA_History (id INT, Column1 nvarchar(30), TimeStamp DateTime)
(此代码不是产品,只是一般的想法) 将以下代码放入存储过程中,并使用带有时间表的Sql Server作业

MERGE INTO dbo.TableA_History
USING dbo.TableA
ON TableA_History.id = TableA.id AND TableA_History.Column1 = TableA.Column1
WHEN NOT MATCHED BY TARGET THEN
INSERT (id,Column1,TimeStamp) VALUES (TableA.id,TableA.Column1,GETDATE())

因此,基本上,如果记录不存在或不匹配意味着列已更改,请将记录插入历史记录表。

在某些情况下,即使未使用SQL Server 2016且系统版本表不可用,也可以创建不带触发器的历史记录

在某些情况下,当您可以确定哪些例程正在修改表时,您可以使用
输出到
中来创建历史记录

比如说,

INSERT INTO [dbo].[MainTable]
OUTPUT inserted.[]
      ,...
      ,'I'
      ,GETUTCDATE()
      ,@CurrentUserID
INTO [dbo].[HistoryTable]
SELECT *
FROM ... ;
在例程中,当您使用
MERGE
时,我喜欢使用
$action

仅对MERGE语句可用。指定类型为的列 nvarchar(10)在返回的MERGE语句的OUTPUT子句中 每行的三个值之一:“插入”、“更新”或“删除”, 根据在该行上执行的操作

我们可以添加修改表的
用户
,这非常方便。使用触发器您需要使用会话上下文或会话变量来传递
用户
。在版本控制表中,您需要向主表添加额外的列,以便记录用户,因为它只记录当前表列(至少目前是这样)

因此,基本上这取决于您的数据和应用程序。如果表上有许多积垢源,触发器是最安全的方法。如果您的表很大且使用量很大,那么使用
MERGE
是不好的,因为它会导致阻塞并损害性能

在我们的数据库中,我们根据情况使用所有方法:

  • 遗留问题的触发器
  • 新开发的系统版本控制
  • 当确保数据仅由给定的一组例程修改时,在历史记录中直接输出

谢谢。我完全同意触发器是一种方式。但这是一个否定:(这里是。thatsy!。你有一个例子吗?或者之前有一个存储过程回答了这个问题吗?我希望看到一个例子。我创建了一个游标来捕获更改,然后将其作为作业计划。但是我希望通过合并创建一些新的内容!SQL Server 2016引入了对系统版本的时态表的支持,作为一种数据库功能,它可以gs内置支持提供有关存储在表中任何时间点的数据的信息,而不仅仅是当前时刻正确的数据。谢谢DanB。这适用于一列。因此我必须用于表中的所有25列。是吗?是的,您的ON子句将连接所有25列。我知道这是一个痛苦,但我的数据仓库中确实有一些合并,它们可以实现这种连接。关于TableA_History.id=TableA.id和TableA_History.Column1=TableA.Column1和TableA_History.Column2=TableA.Column2等等。