我第一次使用XML,似乎很难将变量传递给XML查询的单例。执行查询时显示的错误是“ XML数据类型方法“值”的参数1必须为字符串文字”
我已将变量设置为数据类型varchar。我在这里想念什么?
----Inside LOOP----
SELECT @count = @count + 1
select
a.XMLData.value('(//FlightInfo/TailNumber/text())['''+ @count +''']', 'varchar(100)') TaiNumber
from
XMLwithOpenXML a
是否有更简单的方法来遍历XML节点以修改那些数据不正确/丢失的节点?
我试图遍历“ TailNumber”节点,然后使用某种联接或where子句以正确的TailNumber更新节点值
答案 0 :(得分:0)
AFAIK,SQL Server仍然不支持position()
函数作为输出,仅作为过滤条件。因此,没有简单的方法可以按自然顺序对节点进行编号。我见过的所有解决方案都通过对所有前面的节点进行计数来计算每个节点的位置,从而产生一个半笛卡尔式的方法,这消除了在体面大小的XML上对性能的所有希望。
但是,您可以使用大约8年前我使用的相当肮脏的把戏。您可以生成单调的数字序列,并使用它们查找对应位置的节点。下面的代码说明了该方法:
-- Sample data
declare @t table (
Id int identity(1,1) primary key,
XMLData xml not null
);
insert into @t (XMLData)
values (N'<r>
<Item>First Value</Item>
<Item>Second</Item>
</r>'),
(N'<r>
<Item>Another One</Item>
<Item>123456</Item>
<Item>The last</Item>
</r>');
declare @NodeCount int;
-- Get the largest amount of nodes among the rows of interest
select @NodeCount = max(t.XMLData.value('count(/r/Item)', 'int'))
from @t t;
select t.Id, n.RN, i.c.value('./text()[1]', 'varchar(100)') as [NodeValue]
from @t t
cross join (
-- Generate a number sequence for each /r/Item node in every row
select top (@NodeCount) row_number() over(order by (select null)) as [RN]
from sys.all_objects
) n
-- Get N-th node
cross apply t.XMLData.nodes('/r/Item[position() = sql:column("n.RN")]') i(c)
order by t.Id, n.RN;
对于在具有几百万行和/或大型XML Blob的表上运行它要小心。在此示例中,它运行得非常整洁,但我不知道在实际情况下它将有多高效。如果您的XML很大,或者要查询的行很多,那么更好的解决方案可能是通过使用除SQL之外的其他语言添加节点号作为属性来预处理XML。例如,CLR功能可能对此要好得多。
P.S。尽管如此,应该比循环还快...