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

发布于 2024-07-09 21:46:49 字数 830 浏览 8 评论 0原文

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

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

In the tradition of this question and in light of the documentation, how does one make this function deterministic:

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

Or this one (because of the string/date literals - and yes, I've also tried '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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘你却要生生世世 2024-07-16 21:46:50

从您链接的文章中:

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

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

例如:

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

除非不要使用 121...

From the articles you linked:

To be deterministic, the style parameter must be a constant. Additionally, styles less than or equal to 100 are nondeterministic, except for styles 20 and 21. Styles greater than 100 are deterministic, except for styles 106, 107, 109 and 113.

You need to use a style parameter in your conversions to datetime.

For example:

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

Except don't use 121...

栀子花开つ 2024-07-16 21:46:49

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 的日期时间链接数据类型):

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

BOL says that CONVERT is deterministic with datetimes if the style parameter is specified. So if you change the first UDF to:

RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID), 112)

Then it should be deterministic, if I understand the docs correctly.

Presumably, the same trick could be used in your second UDF:

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

I really wish there were a way to specify datetime literals in T-SQL.

EDIT:

As pointed out by Arvo in the comments (thank you, Arvo), the ODBC timestamp literal format can be used (even when using OLE DB) so the second function above could be better written as:

IF @DateTimeIn < {d '1900-01-01'}
    RETURN {d '1900-01-01'}
...etc.

and the conversion to datetime is done at compile time instead of execution time. Note that the format of the date has to be very specific (see Arvo's link to the datetime data type):

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文