7

根据这个问题的传统和文档,如何使这个函数具有确定性:

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
4

2 回答 2

7

BOL 表示,如果指定了样式参数,则日期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]

于 2008-11-21T20:50:02.543 回答
5

从您链接的文章中:

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

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

例如:

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

除了不要使用 121...

于 2008-11-21T20:35:20.013 回答