【问题标题】:SQLCLR and DateTime2SQLCLR 和 DateTime2
【发布时间】:2011-02-06 21:51:20
【问题描述】:

使用 SQL Server 2008、Visual Studio 2005、.net 2.0 和 SP2(支持新的 SQL Server 2008 数据类型)。

我正在尝试编写一个 SQLCLR 函数,该函数将 DateTime2 作为输入并返回另一个 DateTime2。例如:

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace MyCompany.SQLCLR
{
    public class DateTimeHelpCLR
    {
        [SqlFunction(DataAccess = DataAccessKind.None)]
        public static SqlDateTime UTCToLocalDT(SqlDateTime val)
        {
            if (val.IsNull)
                return SqlDateTime.Null;

            TimeZone tz = System.TimeZone.CurrentTimeZone;
            DateTime res = tz.ToLocalTime(val.Value);

            return new SqlDateTime(res);
        }
    }
}

现在,上面的编译正常。我希望这些 SqlDateTimes 映射到 SQL Server 的 DateTime2,所以我尝试运行这个 T-SQL:

CREATE function hubg.f_UTCToLocalDT
(
    @dt DATETIME2
)
returns DATETIME2
AS
EXTERNAL NAME [SQLCLR].[MyCompany.SQLCLR.DateTimeHelpCLR].UTCToLocalDT
GO

这会产生以下错误:

消息 6551,级别 16,状态 2,程序 f_UTCToLocalDT,第 1 行 CREATE FUNCTION “f_UTCToLocalDT”失败,因为 返回值的 T-SQL 和 CLR 类型 不匹配。

使用 DATETIME(而不是 DATETIME2)可以正常工作。但我宁愿使用 DATETIME2 来支持提高的精度。我做错了什么,还是 SQLCLR 不(完全)支持 DateTime2 ?

【问题讨论】:

    标签: c# .net tsql sql-server-2008 sqlclr


    【解决方案1】:

    您需要更改函数方法签名中的 DateTime 类型。 SQLDateTime 映射到数据库上的 DateTime。

    System.DateTime 更精确,可以映射到 DateTime2(但默认情况下,它会在部署脚本中作为 DateTime 删除)。

    [SqlFunction(DataAccess = DataAccessKind.None)]
    //OLD Signature public static SqlDateTime UTCToLocalDT(SqlDateTime val) 
    public static DateTime UTCToLocalDT(DateTime val) {
       ...
    }
    

    然后你可以调整你的部署脚本来读取。

    CREATE FUNCTION [UTCToLocalDT]
    (
        @dt [datetime2]
    )
    RETURNS [datetime2]
    AS
        EXTERNAL NAME [SQLCLR].[MyCompany.SQLCLR.DateTimeHelpCLR].UTCToLocalDT
    GO
    

    现在运行你的函数应该会给你更精确的输出。

    DECLARE @input DateTime2, @output DateTime2
    SET @input = '2010-04-12 09:53:44.48123456'
    SET @output = YourDatabase.dbo.[UTCToLocalDT](@input)
    SELECT @input, @output
    

    【讨论】:

    • 谢谢。这种技术是否支持传递和返回 NULL?
    • 如何调整部署脚本?当您在 Visual Studio 中右键单击并选择“部署”时,就我而言没有一个。 SqlFunction 属性的全部意义在于使该过程自动化,因此您只需从右键菜单中选择部署即可。
    • 不...这不支持空值,因为您必须使用 Nullable,这似乎不受支持。即使在 Visual Studio 2010 Ultimate 中也无法部署。
    • @MoeSisko:是的,它支持 NULL。你只需要使用“日期时间?”而不是“日期时间”。我已经针对输入参数和返回类型对此进行了测试,编译后的代码在 SQL Server 2008(在 R2 上测试)和 2012 中都有效。由于 DateTime 不是 SQL 类型,您可以通过“== null”而不是测试空值比 SQL 类型中的“.IsNull”。
    • @Triynko:是的,实际上支持 NULL。我只是在之前对 Moe 的评论中提供了详细信息,但每条评论不能只标记一个人。
    【解决方案2】:

    注意使用“日期时间?”仍然总是给出构建错误(即使在带有 sql 2012 的 VS 2013 中),但显然如果选择“构建,部署”然后使用 obj 文件夹中的文件,在 sql 查询窗口中编辑 generate.sql 文件,结果是可用的(使用 DateTime2 作为参数)在执行之前将其添加到 Sql Server。
    构建错误是“SQL46010: ) 附近的语法不正确。” 在 \obj\Debug\YourPrjName.generated.sql

    (如果可以的话,我会在上面发表评论。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多