问题描述
我正在尝试使下面的代码动态化,因为页面“节点”中的“名称”属性可以有不同的名称。
当我运行下面的代码时,它返回错误 'XQuery [value()]: 'value()' requires a singleton (or empty sequence),found operand of type 'xdt:untypedAtomic *''
我觉得我的主要问题是在线 'C.value('(/level1/level2/template/page/@name)[sql:variable("@Counter")]','NVARCHAR(MAX)') AS [页面名称]' 我试图使 '@counter' 变量动态化。
请问大家有什么解决办法吗?
XML FOR ID 9371
<level1>
<level2>
<template width="594" height="500">
<page Cid="1" name="Test Page Name" colour="-3355393">
<image Cid="8" x="432" y="8" w="148" h="95" KeyImage="32861" Ratio="y" />
<formattedText Cid="14" x="9" y="22" w="253" h="38">
<p>
<p>
Text
</p>
</p>
</formattedText>
</page>
<page Cid="6" name="Properties">
<formattedText Cid="7" x="200" y="148" w="208" h="228">
<p>
<p>
<t>Created by </t>
<t b="b">Joe Bloggs</t>
</p>
<p />
<p>
<t>Date published 30/05/2017</t>
</p>
</formattedText>
</page>
</template>
</level2>
</level1>
** 呈现结果
Page Name | Demographics
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Test Page Name | <page Cid="1" name="Test Page Name" colour="-3355393"><image Cid="8" x="432" y="8" w="148" h="95" KeyImage="32861" Ratio="y" /><formattedText Cid="14" x="9" y="22" w="253" h="38"><p><p>Text</p></p> </formattedText></page>
Test Page Name | <page><formattedText Cid="7" x="200" y="148" w="208" h="228"><p><p> <t>Created by </t><t b="b">Joe Bloggs</t></p><p /><p><t>Date published 30/05/2017</t> </p></formattedText></page>
** 想要的结果
Page Name | Demographics
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Test Page Name | <page Cid="1" name="Test Page Name" colour="-3355393"><image Cid="8" x="432" y="8" w="148" h="95" KeyImage="32861" Ratio="y" /><formattedText Cid="14" x="9" y="22" w="253" h="38"><p><p>Text</p></p> </formattedText></page>
Properties | <page><formattedText Cid="7" x="200" y="148" w="208" h="228"><p><p> <t>Created by </t><t b="b">Joe Bloggs</t></p><p /><p><t>Date published 30/05/2017</t> </p></formattedText></page>
DECLARE @TableName VARCHAR(40),@opxml AS XML,@hDoc AS INT,@sql NVARCHAR (MAX)
SELECT @opxml =
a.[filedata]
FROM [database].[dbo].[xmlfile2] a
where [Id] = 9371
DECLARE @Counter INT
DECLARE @MaxNo INT
SET @Counter=1
SET @MaxNo=(SELECT
COUNT(CAST('<page>' + CAST(C.query('./child::node()') as nvarchar(max)) + '</page>' as xml))
FROM @opxml.nodes('/level1/level2/template/page') AS T(C))
WHILE ( @Counter <= @MaxNo)
BEGIN
SELECT
C.value('(/level1/level2/template/page/@name)[sql:variable("@Counter")]','NVARCHAR(MAX)') AS
[Page Name],CAST('<page>' + CAST(C.query('./child::node()') as nvarchar(max)) + '</page>' as xml) AS [Page_XML],ROW_NUMBER() OVER (ORDER BY t.c)
FROM @opxml.nodes('/level1/level2/template/page') AS T(C)
SET @Counter = @Counter + 1
END
解决方法
我觉得
SELECT
C.value('@name','NVARCHAR(MAX)') AS [Page Name],C.query('<page>{node()}</page>') AS [Page_XML],ROW_NUMBER() OVER (ORDER BY t.c)
FROM @opxml.nodes('/level1/level2/template/page') AS T(C)
可能足以产生所需的结果,而无需 WHILE 循环。
我认为value()
(例如C.value('(/level1/level2/template/page/@name)[sql:variable("@Counter")]','NVARCHAR(MAX)')
)内部的长路径的原始问题是由于SQL服务器中XQuery的静态类型检查,为了避免它,您基本上需要添加另一个谓词确保类型检查器知道返回单个值,例如C.value('(/level1/level2/template/page/@name)[sql:variable("@Counter")][1]','NVARCHAR(MAX)')
对我来说,代码
DECLARE @opxml AS XML
SET @opxml = N'<level1>
<level2>
<template width="594" height="500">
<page Cid="1" name="Test Page Name" colour="-3355393">
<image Cid="8" x="432" y="8" w="148" h="95" KeyImage="32861" Ratio="y" />
<formattedText Cid="14" x="9" y="22" w="253" h="38">
<p>
<p>
Text
</p>
</p>
</formattedText>
</page>
<page Cid="6" name="Properties">
<formattedText Cid="7" x="200" y="148" w="208" h="228">
<p>
<p>
<t>Created by </t>
<t b="b">Joe Bloggs</t>
</p>
<p />
<p>
<t>Date published 30/05/2017</t>
</p>
</p>
</formattedText>
</page>
</template>
</level2>
</level1>'
SELECT
C.value('@name',ROW_NUMBER() OVER (ORDER BY t.c)
FROM @opxml.nodes('/level1/level2/template/page') AS T(C)
制作桌子
Page Name Page_XML (Kein Spaltenname)
Test Page Name <page><image Cid="8" x="432" y="8" w="148" h="95" KeyImage="32861" Ratio="y" /><formattedText Cid="14" x="9" y="22" w="253" h="38"><p><p>
Text
</p></p></formattedText></page> 1
Properties <page><formattedText Cid="7" x="200" y="148" w="208" h="228"><p><p><t>Created by </t><t b="b">Joe Bloggs</t></p><p /><p><t>Date published 30/05/2017</t></p></p></formattedText></page> 2
所以至少 Page_Name
似乎很容易通过使用例如C.value('@name','NVARCHAR(MAX)') AS [Page Name]