在 Apply 块中使用需要表参数的标量函数
Posted
技术标签:
【中文标题】在 Apply 块中使用需要表参数的标量函数【英文标题】:Using a Scalar Function that expects a Table Parameter inside an Apply block 【发布时间】:2020-12-02 06:23:54 【问题描述】:TLDR:我有一个标量函数,它需要一个表值参数并返回该表的 XML 表示。现在我需要在更大的 Update 语句中使用这个函数,其中函数的表参数由内部 Select 语句生成。
嗨,
我们有一个 XML 类型定义,比如 [dbo].[XmlTestType],它看起来像这样:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Element" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Content" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="Name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
它基本上表示元素-内容映射的集合,每个元素(具有名称属性)包含 N 个元素(字符串类型)。
我们也有这个表格类型的定义:
CREATE TYPE [dbo].[TableTestType] AS TABLE
(
[Element] VARCHAR(255) NOT NULL
,[Content] VARCHAR(255) NOT NULL
,PRIMARY KEY CLUSTERED ( [Element], [Content] )
);
到目前为止很简单。我们还有两个函数,可以在此数据模型的 XML 和表格表示之间进行转换:
带有 [dbo].[TableTestType] 类型表参数的标量函数,它返回 [dbo].[XmlTestType] 类型的 xml。我们称它为 [dbo].[ConvertTableToXml]。 具有 [dbo].[XmlTestType] 类型的 xml 参数的表值函数,它返回 [dbo].[TableTestType] 类型的表。我们称它为 [dbo].[ConvertXmlToTable]。我们有一个单独的表,它在其中一列中使用 xml 数据类型:
CREATE TABLE [dbo].[SomeTable]
(
[UID] INT NOT NULL IDENTITY(1,1)
,[XmlData] XML (DOCUMENT [dbo].[XmlTestType]) NULL
);
到目前为止一切正常,但现在我需要在 Update 语句中更新 Table 内的 XmlData。 例如,要修改所有行的 XmlData,以包含单独表的值。 所以我希望 做这样的事情:
DECLARE @newDataForSomeTable AS TABLE
(
[FK_dbo__SomeTable__UID] INT NOT NULL
,[Element] VARCHAR(255) NOT NULL
,[Content] VARCHAR(255) NOT NULL
);
/* @newDataForSomeTable gets filled */
UPDATE [tbl] SET [tbl].[XmlData] = [calc].[XmlData]
FROM [dbo].[SomeTable] AS [tbl]
CROSS APPLY
(
SELECT [dbo].[ConvertTableToXml](
SELECT
[currentState].[Element]
,[currentState].[Content]
FROM [dbo].[ConvertXmlToTable]([tbl].[XmlData]) AS [currentState]
UNION
SELECT
[newData].[Element]
,[newData].[Content]
FROM @newDataForSomeTable AS [newData]
WHERE [newData].[FK_dbo__SomeTable__UID] = [tbl].[UID]
) AS [XmlData]
) AS [calc]
这样的事情可能吗?意思是在 Apply 块内调用一个需要表值参数的标量函数,其中表值参数是使用内部 select 语句生成的?
现在我别无选择,只能将光标移到表上,从行的当前状态生成类型为 [dbo].[TableTestType] 的表变量,将缺少的条目插入该变量,然后将表转换回来转为 XML;逐行更新。
亲切的问候,弗兰克
【问题讨论】:
除了与 XML 之间的转换之外,您的函数中是否有任何特殊逻辑?否则,我不明白你为什么不能简化更新到UPDATE [tbl] SET [tbl].[XmlData] = [calc].[XmlData] FROM [dbo].[SomeTable] AS [tbl] JOIN @newDataForSomeTable AS [calc] ON [tbl].[UID]=[calc].[UID]
【参考方案1】:
[我可以] 在 Apply 块中调用一个标量函数,该函数需要一个表值参数
没有。无法在 SELECT 中构造表值类型。您必须声明一个表类型的变量,然后插入它。
或者,您可以嵌入 xml.nodes 解析逻辑,将 XML 转换为表到调用查询的正文中。
【讨论】:
以上是关于在 Apply 块中使用需要表参数的标量函数的主要内容,如果未能解决你的问题,请参考以下文章