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

Cad*_*oux 7 sql sql-server sql-server-2005 deterministic user-defined-functions

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

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
Run Code Online (Sandbox Code Playgroud)

或者这个(因为字符串/日期文字 - 是的,我也试过'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
Run Code Online (Sandbox Code Playgroud)

P D*_*ddy 7

如果指定了样式参数,BOL表示对日期时间CONVERT 具有确定性.因此,如果您将第一个UDF更改为:

RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID), 112)
Run Code Online (Sandbox Code Playgroud)

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

据推测,可以在第二个UDF中使用相同的技巧:

IF @DateTimeIn < CONVERT(datetime, '1/1/1900', 101)
    RETURN CONVERT(datetime, '1/1/1900', 101)
Run Code Online (Sandbox Code Playgroud)

真的希望有一种方法可以在T-SQL中指定日期时间文字.

编辑:

正如Arvo在评论中所指出的那样(感谢 Arvo),可以使用ODBC时间戳文字格式(即使使用OLE DB),因此上面的第二个函数可以更好地编写为:

IF @DateTimeIn < {d '1900-01-01'}
    RETURN {d '1900-01-01'}
...etc.
Run Code Online (Sandbox Code Playgroud)

转换为datetime是在编译时而不是执行时完成的.请注意,日期的格式必须非常具体(请参阅Arvo指向日期时间数据类型的链接):

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

  • 关于datetime文字 - 你不能使用像{d'1990-10-02'}这样的ODBC时间戳格式吗?来自http://msdn.microsoft.com/en-us/library/ms187819.aspx:使用ADO,OLE DB和基于ODBC的API的应用程序可以使用此ODBC时间戳格式来表示日期和时间. (2认同)

Amy*_*y B 5

从您链接的文章中:

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

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

例如:

CONVERT(datetime, '2008-01-01', 121)
Run Code Online (Sandbox Code Playgroud)

除了不要使用 121 ...