ValidFrom 可以在 UDF 中使用,但 ValidTo - 不行吗? (时态表中的计算列)
ValidFrom can be used in UDF, but ValidTo - not? (computed columns in temporal tables)
请指教-我在这里缺少什么?
时态表 ValidTo 字段不能用作计算列中 UDF 的参数,而 ValidFrom 可以正常工作。
SQL 服务器 2016.
有个例子。
在这种情况下,记录 "Masha" 必须将 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
我找到了它发生的原因:
- 临时 table 存储操作发生前的数据状态。
- Temporal table history table 没有任何计算列,即使 main table 有。
- 临时table将计算列存储为值(计算值)
- 当记录即将被删除时 WhenDeleted 标志在这个阶段仍然是 NULL 并且这个 NULL 正在被记录到历史记录 Table 在操作之前
- 然后主 table 中的记录被删除,但是这个 WhenDeleted 计算从未真正发生,并且这个计算的结果永远不会存储在任何地方
请指教-我在这里缺少什么? 时态表 ValidTo 字段不能用作计算列中 UDF 的参数,而 ValidFrom 可以正常工作。
SQL 服务器 2016.
有个例子。 在这种情况下,记录 "Masha" 必须将 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
我找到了它发生的原因:
- 临时 table 存储操作发生前的数据状态。
- Temporal table history table 没有任何计算列,即使 main table 有。
- 临时table将计算列存储为值(计算值)
- 当记录即将被删除时 WhenDeleted 标志在这个阶段仍然是 NULL 并且这个 NULL 正在被记录到历史记录 Table 在操作之前
- 然后主 table 中的记录被删除,但是这个 WhenDeleted 计算从未真正发生,并且这个计算的结果永远不会存储在任何地方