【问题标题】:Creating a table method on a user defined type (like like 'nodes' on the XML data type)在用户定义的类型上创建表方法(如 XML 数据类型上的“节点”)
【发布时间】:2018-05-18 21:19:30
【问题描述】:

我已经创建了基于 SQLCLR 的用户定义表值函数以及用户定义类型。

我现在想要的是一个返回表的 SQLCLR UDT 上的方法,类似于 XML 数据类型上的 nodes 方法。

SqlMethod 属性/装饰的TableDefinitionFillRowMethodName 属性似乎暗示它应该是可能的,但实际上没有任何效果。当我调用这样的方法时(我预计会失败):

SELECT @Instance.AsTable();

我明白了:

无效的数据类型

如果我以这种方式调用 SQLCLR 表值函数,这与我得到的错误不同。

当我这样打电话时:

SELECT * FROM @Instance.AsTable();

我收到(可能是预期的)错误:

表值方法返回的表(及其列)需要别名。

当我这样打电话时:

SELECT * FROM @Instance.AsTable() t(c1,c2);

上面写着:

表值函数“AsTable”不能有列别名

我感觉这个问题可能与表函数应该是静态的这一事实有关,所以我也尝试将它实现为扩展方法,但在这种情况下它甚至无法编译。我明白了:

扩展方法必须定义在非泛型静态类中

显然我可以将它实现为一个普通的 SQLCLR 表函数,它需要一个我的 UDT 类型的参数。事实上,我实际上已经做到了这一点并且SELECT * FROM dbo.AsTable(@Instance); 有效,但我不喜欢那个解决方案。我真的很想让这个语法起作用:SELECT * FROM @Instance.AsTable() t(c1,c2);

这是一个非工作版本:

[SqlMethod(IsDeterministic = false, DataAccess = DataAccessKind.None, OnNullCall=true
    , TableDefinition = "RowKey nvarchar(32),RowValue nvarchar(1000)"
    , FillRowMethodName = "FormatLanguageRow")]
public IEnumerable AllRows()
{
    return _rowCollection;
}

【问题讨论】:

    标签: sql-server extension-methods user-defined-functions sqlclr user-defined-types


    【解决方案1】:

    遗憾的是,无法在返回表的 UDT 上创建方法(即返回 IEnumerable)。您对 SqlMethod 属性的两个属性的混淆是可以理解的,因为它们具有误导性。如果您查看 SqlMethodAttribute Class 的 MSDN 页面,您将在“备注”部分看到以下注释:

    SqlMethodAttribute 继承自 SqlFunctionAttribute,因此 SqlMethodAttribute 继承自 SqlFunctionAttribute 的 FillRowMethodNameTableDefinition 字段。请注意,不可能编写表值方法,尽管这些字段的名称可能表明它是可能的。

    在您已经尝试过的解决方法(即创建 TVF)之外,您可以从 UDT 方法将数据作为 XML(即SqlXml)返回。它肯定不会像流式 TVF 那样高效,但它返回的值可以通过 XML 数据类型的 nodes() 方法转换为内联表。


    更新(2017-01-16)

    我已正式将此作为 Microsoft Connect 建议提交:
    Allow CLR UDT to return IEnumerable / Table / TVF from a method ( SqlMethod ) like XML.nodes()

    【讨论】:

    • 现在连接已停用,您的链接已失效。我在这里找到了它,但它不再有任何选票(现在我的除外!)。 feedback.azure.com/forums/908035-sql-server/suggestions/…
    • @bielawski 谢谢。是的,微软通过不转发任何 URL 从 Connect 迁移到 UserVoice 做得非常糟糕。我一直在慢慢更新我的答案中的参考资料,但还没有全部找到。我现在在这里更新了我的答案(并对该建议进行了投票)。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 2019-10-25
    • 2014-04-18
    • 2011-12-15
    相关资源
    最近更新 更多