如何使从varchar到datetime的转换具有确定性?

8

这个问题的传统中,并考虑到文档,如何使此函数确定性:

ALTER FUNCTION [udf_DateTimeFromDataDtID]
(
    @DATA_DT_ID int -- In form YYYYMMDD
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID))
END

或者这个(因为字符串/日期字面量 - 是的,我也尝试过 '1900-01-01'):

ALTER FUNCTION udf_CappedDate
(
    @DateTimeIn datetime
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    IF @DateTimeIn < '1/1/1900'
        RETURN '1/1/1900'
    ELSE IF @DateTimeIn > '1/1/2100'
        RETURN '1/1/2100'

    RETURN @DateTimeIn
END
2个回答

7
BOL称,如果指定了“style”参数,则CONVERT与日期时间有关的确定性函数。因此,如果您将第一个UDF更改为:
RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID), 112)

如果我正确理解文档,那么它应该是确定性的。

可以假设,在你的第二个UDF中也可以使用同样的技巧:

IF @DateTimeIn < CONVERT(datetime, '1/1/1900', 101)
    RETURN CONVERT(datetime, '1/1/1900', 101)

我真的希望有一种方法可以在T-SQL中指定日期时间文字。
编辑:如Arvo在评论中指出(谢谢你,Arvo),可以使用ODBC时间戳文字格式(即使使用OLE DB),因此上面的第二个函数可以更好地编写为:
IF @DateTimeIn < {d '1900-01-01'}
    RETURN {d '1900-01-01'}
...etc.

日期时间转换是在编译时完成的,而不是在执行时完成的。请注意,日期的格式必须非常特定(参见Arvo提供的datetime数据类型链接):

d yyyy-mm-dd
t hh:mm:ss[.fff]
ts yyyy-mm-dd hh:mm:ss[.fff]


我只在将数据转换为 varchar 时使用这种风格 - 文档有点模糊,但我已经尝试过了,它显然是有效的。 - Cade Roux
@P Daddy,日期时间字面量的确很好用。 - Amy B
2
关于日期时间字面量 - 不能使用ODBC时间戳格式,例如{ d '1990-10-02' }吗?来自http://msdn.microsoft.com/en-us/library/ms187819.aspx: 使用ADO、OLE DB和基于ODBC的API的应用程序可以使用此ODBC时间戳格式表示日期和时间。 - Arvo

6

从你提供的文章中可以得知:

为了使结果具有确定性,style 参数必须是一个常量。此外,小于等于 100 的样式是不确定的,除了样式 20 和 21。大于 100 的样式是确定的,除了样式 106、107、109 和 113。

在转换日期时间时,需要使用样式参数。

例如:

CONVERT(datetime, '2008-01-01', 121)

除了不使用121之外...


在UDFs中使用字符串而不转换为日期格式是不行的吗? - Cade Roux
如果字符串被隐式转换为日期,则这些转换缺乏“常量”样式,并将使函数不确定。 - Amy B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接