Cannot delete rows from a temporal history table
If you make the DELETE
dynamic, your stored procedure will successfully ALTER
the table, DELETE
the records in question, and then ALTER
it back.
CREATE PROCEDURE [dbo].[OrderHistoryDelete]
(@Id UNIQUEIDENTIFIER)
AS
BEGIN
DECLARE @sql VARCHAR(MAX)
BEGIN TRANSACTION
ALTER TABLE [dbo].[Order] SET ( SYSTEM_VERSIONING = OFF )
SET @sql = 'DELETE FROM [dbo].[OrderHistory] WITH (TABLOCKX)
WHERE [Id] = ''' + CAST(@Id AS VARCHAR(40)) + ''''
EXEC (@sql)
ALTER TABLE [dbo].[Order] SET ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[OrderHistory]))
COMMIT TRANSACTION
END
I have never have issues like this, but my stored procedure is a little bit different - I am getting CSV of records to be deleted, then STRING_SPLIT
them and materialized in a temporary table. Then, this table is joined to the target history table.
Here is full working example (only one input value). First create the table and add some sample data:
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
Then, create the stored procedure:
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
and now delete a record from the history table:
EXEC [dbo].[usp_StackOverflow_Delete] @Col1 = 1;
SELECT *
FROM [dbo].[StackOverflow];
SELECT *
FROM [dbo].[StackOverflowChanges];
Clean up:
ALTER TABLE [dbo].[StackOverflow] SET ( SYSTEM_VERSIONING = OFF )
DROP TABLE IF EXISTS [dbo].[StackOverflow];
DROP TABLE IF EXISTS [dbo].[StackOverflowChanges];