ValidFrom 可以在 UDF 中使用,但 ValidTo - 不是吗? (时态表中的计算列)

Posted

技术标签:

【中文标题】ValidFrom 可以在 UDF 中使用,但 ValidTo - 不是吗? (时态表中的计算列)【英文标题】:ValidFrom can be used in UDF, but ValidTo - not? (computed columns in temporal tables) 【发布时间】:2018-03-15 02:27:53 【问题描述】:

请告知-我在这里缺少什么? 临时表 ValidTo 字段不能用作计算列中 UDF 中的参数,而 ValidFrom 确实可以正常工作。

SQL Server 2016。

有一个例子。 在这种情况下,记录“Masha”必须将 WhenDeleted 标志显示为日期,而不是 null:

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

【问题讨论】:

【参考方案1】:

我找到了它发生的原因:

临时表存储动作发生前的数据状态。 即使主表有,临时表历史表也没有任何计算列。 临时表将计算列存储为值(计算值) 当记录即将被删除时WhenDeleted标志在这个阶段仍然是NULL并且这个NULL在动作之前被记录到历史表中 然后主表中的记录被删除,但该 WhenDeleted 计算从未真正发生,该计算的结果永远不会存储在任何地方

【讨论】:

以上是关于ValidFrom 可以在 UDF 中使用,但 ValidTo - 不是吗? (时态表中的计算列)的主要内容,如果未能解决你的问题,请参考以下文章

Spark DataFrame UDF 分区列

fluent编译UDF的过程中,出现了语法错误

SQL UDF 和查询优化 [重复]

确定货币或双倍的 UDF 方法

validform的datatype 怎么定义的

是否可以将字符串注册为 UDF?