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

问题描述 投票:0回答:1

我有一个表无意义地将DateTime值存储在Year(INT),Month(INT),Day(INT)和Time(FLOAT)列中;不幸的是,我不允许更改此内容,但需要按年份和月份对表进行分区。因此,我试图创建一个持久的计算列来保持日期时间为DATETIME2格式。但是,当我尝试添加基于它的计算列时,我的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

function tsql calculated-columns deterministic datetime2
1个回答
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不会返回DATETIME2; DATETIME2FROMPARTS还为小数精度采用了一个附加参数 - 这使得我提供的原始DATETIMEFROMPARTS解决方案中出现的舍入错误无效。

© www.soinside.com 2019 - 2024. All rights reserved.