如何创建返回DATETIME2的确定性函数?

时间:2019-04-16 09:48:27

标签: function tsql calculated-columns deterministic datetime2

我有一个表,该表毫无意义地将DateTime值存储在Year(INT),Month(INT),Day(INT)和Time(FLOAT)列中;不幸的是,我不允许更改此设置,但要求按年和月对表进行分区。因此,我试图创建一个持久化的计算列,以DATETIME2格式保存DateTime。但是,当我尝试根据其标量添加计算列时,我的CreateDateTime标量函数被认为是“不确定的”。

这是我的CreateDateTime函数。

CREATE FUNCTION dbo.CreateDateTime
(
    @year SMALLINT,
    @month TINYINT,
    @day TINYINT,
    @time FLOAT
)
RETURNS DATETIME2
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @paddedYear VARCHAR(4) = FORMAT(@year, '0000')
    DECLARE @paddedMonth VARCHAR(2) = FORMAT(@month, '00')
    DECLARE @paddedDay VARCHAR(2) = FORMAT(@day, '00')
    DECLARE @formattedTime VARCHAR(8) = FORMAT(@time, '00:00:00')
    RETURN IIF
    (
        @year IS NULL
        OR @month IS NULL
        OR @day IS NULL,
        NULL,
        CAST
        (
            IIF
            (
                @time IS NULL OR TRY_CONVERT(TIME, @formattedTime) IS NULL,
                @paddedYear
                + @paddedMonth
                + @paddedDay,
                @paddedYear
                + @paddedMonth
                + @paddedDay
                + ' '
                + @formattedTime
            )
            AS DATETIME2
        )
    )
END

但是,当为了尝试为DateTime添加计算列(使用以下脚本)时,它导致以下错误消息。

ALTER TABLE dbo.Logs
ADD [DateTime] AS (dbo.CreateDateTime(RY, RM, RD, RT)) PERSISTED
  

表'Logs'中的计算列'DateTime'无法保存,因为该列不确定。

我尝试将CreateDateTime更改为一个非常基本的函数,该函数使用以下内容返回固定的DateTime:CAST('20000101' AS DATETIME2)CONVERT(DATETIME2, '20000101')'20000101',但都产生相同的结果错误如上。尽管设法使CreateDateTime函数返回一个VARCHAR(8),但是我设法添加了该列,所以看起来DATETIME2似乎有问题。

如何创建此CreateDateTime函数,使其被视为确定性函数,并且仍返回DATETIME2

1 个答案:

答案 0 :(得分:2)

通过绕过我的CreateDateTime函数,我可以创建持久化的计算列,而改为使用以下代码:

ALTER TABLE dbo.Logs
ADD [DateTime] AS DATETIME2FROMPARTS
(
    RY,
    RM,
    RD,
    ROUND(RT / 10000, 0, 1),
    ROUND(RT / 100, 0, 1) - ROUND(RT / 10000, 0, 1) * 100,
    ROUND(RT, 0, 1) - ROUND(RT / 100, 0, 1) * 100,
    RT - ROUND(RT, 0, 1),
    3 --Precision to 3 decimal places (for milliseconds)
) PERSISTED

虽然这不能回答我有关创建返回DATETIME2的确定性函数的问题;它确实解决了我创建一个DateTime2持久计算列以显示每个RY,RM,RD和RT值的DateTime时遇到的特定问题。

如Zohar所强调的,DATETIMEFROMPARTS不返回DATETIME2DATETIME2FROMPARTS还采用了一个十进制精度的加法参数-使我提供的原始DATETIMEFROMPARTS解决方案中存在的舍入误差无效。