无法从时间历史记录表中删除行

时间:2018-12-12 15:22:39

标签: sql-server tsql

我最近在SQL Server中发现了临时表。我想开始使用此功能。但是,最大的障碍是无法从中删除记录。由于符合GDPR,这是绝对必须的。

从历史记录表中删除记录显然会导致错误:

  

无法从时间历史记录表中删除行

为了能够从历史表中删除记录,我必须禁用SYSTEM_VERSIONING,然后删除,然后重新启用SYSTEM_VERSIONING。除非有我不知道的另一种方式?

由于无法在存储过程/ SqlCommand中使用GO,因此如何确保删除历史记录不会与其他事务混淆,例如在从历史记录表中删除记录的过程中发送到临时表的更新仍然会导致将记录添加到历史记录表中吗?

我尝试创建一个存储过程以将其包装在一个事务中,但这失败了,因为未执行禁用ALTER TABLE的{​​{1}}语句,但会导致相同的错误。

SYSTEM_VERSIONING

2 个答案:

答案 0 :(得分:1)

如果使WHERE动态,则存储过程将成功UPDATE People SET Username = CONCAT('domainname\',LEFT([E-mailAddress],CHARINDEX('@',[E-mailAddress])-1)) WHERE Username <> CONCAT('domainname\',LEFT([E-mailAddress],CHARINDEX('@',[E-mailAddress])-1)); 表,DELETE有问题的记录,然后ALTER将其返回。

DELETE

答案 1 :(得分:0)

我从来没有遇到过这样的问题,但是我的存储过程有点不同-我要删除记录的CSV,然后STRING_SPLIT并在临时表中实现它们。然后,将该表连接到目标历史记录表。

这里是完整的工作示例(仅一个输入值)。首先创建表并添加一些示例数据:

DROP TABLE IF EXISTS [dbo].[StackOverflow];
GO

CREATE TABLE [dbo].[StackOverflow]
(
    [Col1] INT PRIMARY KEY
   ,[Col2] VARCHAR(32)
   ,[SysStartTime] DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL 
   ,[SysEndTime] DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL 
   ,PERIOD FOR SYSTEM_TIME ([SysStartTime],[SysEndTime])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.StackOverflowChanges));

GO

INSERT INTO [dbo].[StackOverflow] ([Col1], [Col2])
VALUES (1, 'value 1')
      ,(2, 'value 2')
      ,(3, 'value 3');

GO

UPDATE [dbo].[StackOverflow]
SET [Col2] = [Col2] + ' v2'

GO

SELECT *
FROM [dbo].[StackOverflow];

SELECT *
FROM [dbo].[StackOverflowChanges];

GO

enter image description here

然后,创建存储过程:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE OR ALTER PROCEDURE [dbo].[usp_StackOverflow_Delete]
(
    @Col1 INT
)
AS
BEGIN;

    SET NOCOUNT, XACT_ABORT ON;

        DROP TABLE IF EXISTS #RecordsTobeDeleted; 

        CREATE TABLE #RecordsTobeDeleted
        (
            [Col1] INT
        );

        INSERT INTO #RecordsTobeDeleted ([Col1])
        VALUES (@Col1);

        BEGIN TRY

            BEGIN TRANSACTION;

                ALTER TABLE [dbo].[StackOverflow] SET ( SYSTEM_VERSIONING = OFF )

                DELETE [dbo].[StackOverflowChanges]
                FROM [dbo].[StackOverflowChanges] SOC
                INNER JOIN #RecordsTobeDeleted R
                    ON SOC.[Col1] = R.[Col1];

                ALTER TABLE [dbo].[StackOverflow] SET ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[StackOverflowChanges]))
            
            COMMIT TRANSACTION;

        END TRY

        BEGIN CATCH 
  
            IF @@TRANCOUNT > 0
            BEGIN;
                ROLLBACK TRANSACTION;
            END;

            THROW;
            
        END CATCH

    SET NOCOUNT, XACT_ABORT ON;

END;

GO

现在从历史记录表中删除一条记录:

EXEC  [dbo].[usp_StackOverflow_Delete] @Col1 = 1;
 

SELECT *
FROM [dbo].[StackOverflow];

SELECT *
FROM [dbo].[StackOverflowChanges];

enter image description here

清理:

ALTER TABLE [dbo].[StackOverflow] SET ( SYSTEM_VERSIONING = OFF )
DROP TABLE IF EXISTS [dbo].[StackOverflow];
DROP TABLE IF EXISTS [dbo].[StackOverflowChanges];