ValidFrom можно использовать в UDF, а ValidTo - нет? (вычисляемые столбцы во временных таблицах)

Пожалуйста, посоветуйте - что мне здесь не хватает? Временные таблицы Поле ValidTo нельзя использовать в качестве параметра в UDF в вычисляемом столбце, тогда как ValidFrom работает без проблем.

SQL Server 2016

Есть пример. Запись "Маша" в этом случае должна иметь флаг WhenDeleted, отображаемый как дата, а не как ноль:

GO
DROP FUNCTION IF EXISTS [dbo].[VitalyUTCtoDate];
GO
CREATE FUNCTION [dbo].[VitalyUTCtoDate] (@UTCDate DATETIME2)
RETURNS DATETIME2 WITH SCHEMABINDING AS  
BEGIN 
    RETURN CASE WHEN @UTCDate < '9999-01-01' THEN DATEADD(HOUR, DATEDIFF(HOUR, GETUTCDATE(), GETDATE()), @UTCDate) ELSE NULL END;
END
GO

IF EXISTS(SELECT 1 FROM sys.tables t WHERE t.name = 'VitalyTest')
BEGIN
    EXEC('ALTER TABLE [dbo].[VitalyTest] SET (SYSTEM_VERSIONING = OFF)');
    EXEC('DROP TABLE IF EXISTS [dbo].[VitalyTest]');
    EXEC('DROP TABLE IF EXISTS [dbo].[VitalyTestHistory]');
END
GO
CREATE TABLE [dbo].[VitalyTest](
     [ID] [bigint] IDENTITY(1,1) NOT NULL 
    ,[Name] NVARCHAR(255) NOT NULL
    ,[Value] INT NULL
    ,[ValidFrom] DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN 
    ,[ValidTo] DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN
    ,[WhenCreated] AS dbo.VitalyUTCtoDate(ValidFrom)
    ,[WhenDeleted] AS dbo.VitalyUTCtoDate(ValidTo)
    ,CONSTRAINT [PK_VitalyTest] PRIMARY KEY CLUSTERED ([ID] ASC)
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ,PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[VitalyTestHistory]))
GO

-- Insert Data
INSERT INTO dbo.VitalyTest(Name,Value)VALUES('Vasya',234),('Masha',756);

-- Delete Data
DELETE FROM dbo.VitalyTest WHERE Name = 'Masha';

-- Check resutls
SELECT v.*,v.ValidFrom,v.ValidTo
FROM dbo.VitalyTest FOR SYSTEM_TIME ALL AS v
;

-- Clean-up
GO
IF EXISTS(SELECT 1 FROM sys.tables t WHERE t.name = 'VitalyTest')
BEGIN
    EXEC('ALTER TABLE [dbo].[VitalyTest] SET (SYSTEM_VERSIONING = OFF)');
    EXEC('DROP TABLE IF EXISTS [dbo].[VitalyTest]');
    EXEC('DROP TABLE IF EXISTS [dbo].[VitalyTestHistory]');
END
GO
DROP FUNCTION IF EXISTS [dbo].[VitalyUTCtoDate];
GO

Результаты

0 ответов

Я нашел, почему это происходит:

  • Временная таблица хранит состояние данных до того, как произойдет действие.
  • В таблице истории темпоральной таблицы нет вычисляемых столбцов, даже если в основной таблице нет.
  • Временная таблица хранит вычисляемый столбец как значения (вычисленные значения)
  • Когда запись будет удалена, когда на этом этапе флаг WhenDeleted все еще равен NULL, и этот NULL записывается в таблицу истории перед действием
  • Затем запись в основной таблице удаляется, но это вычисление WhenDeleted фактически никогда не происходит, и результат этого вычисления никогда нигде не сохраняется