Sql 如何在存储过程中访问游标上方的XML节点?
我正试图通过存储过程将xml文件导入MSSQL 2012服务器。正如您在xml文件中看到的,它由我要导入到表中的两个节点组成:Sql 如何在存储过程中访问游标上方的XML节点?,sql,sql-server,xml,sqlxml,Sql,Sql Server,Xml,Sqlxml,我正试图通过存储过程将xml文件导入MSSQL 2012服务器。正如您在xml文件中看到的,它由我要导入到表中的两个节点组成: 生产订单——而此表中的一条记录表示一个xml文件 操作-生产订单由n个操作组成 bom\u物料-一个操作由n个消耗的物料组成 我在插入bom\u项目表时遇到困难。我尝试了以下(部分)程序。我这里的问题是我无法访问操作id,或者更确切地说,它在数据库中仍然是空的。通常可以通过这种方式访问ConsumedItem上方的节点,还是我的方法错误 /** INSERT FOR b
生产订单
——而此表中的一条记录表示一个xml文件
操作
-生产订单由n个操作组成
bom\u物料
-一个操作由n个消耗的物料组成
我在插入bom\u项目
表时遇到困难。我尝试了以下(部分)程序。我这里的问题是我无法访问操作id,或者更确切地说,它在数据库中仍然是空的。通常可以通过这种方式访问ConsumedItem上方的节点,还是我的方法错误
/** INSERT FOR bom_items **/
DECLARE db_cursor CURSOR FOR
SELECT
bom_id = line.value('(ItemID/ID)[1]','nvarchar(255)'),
operation_id = line.value('(../ID)[1]','nchar(10)'),
stock_id = line.value('(Location/ID)[1]','nvarchar(255)'),
article_description = line.value('(Description)[1]','nvarchar(255)'),
line_number = line.value('(LineNumber)[1]','int'),
quantity = line.value('(Quantity)[1]','float')
FROM @xmlData.nodes('/DataArea/ProductionOrder/ProductionOrderDetail/BillOfResources/Operations/ConsumedItem')as A(line)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @bom_id, @operation_id, @stock_id, @article_description, @line_number, @quantity
WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS (SELECT * FROM bom_items WHERE production_order_id = @production_order_id AND line_number = @line_number AND operation_id = @operation_id)
UPDATE bom_items
SET bom_id = @bom_id,
stock_id = @stock_id,
article_description = @article_description,
quantity = @quantity
WHERE production_order_id = @production_order_id AND line_number = @line_number
ELSE
INSERT INTO bom_items (bom_id, production_order_id, stock_id, operation_id, article_description, line_number, quantity)
SELECT @bom_id, @production_order_id, @stock_id, @operation_id, @article_description, @line_number, @quantity
FETCH NEXT FROM db_cursor INTO @bom_id, @stock_id, @operation_id, @article_description, @line_number, @quantity
END
CLOSE db_cursor
DEALLOCATE db_cursor
XML文件:
<DataArea>
<ProductionOrder>
<ProductionOrderHeader type="ShopFloor">
[...]
</ProductionOrderHeader>
<ProductionOrderDetail>
<Sequence>1</Sequence>
<Status>
<Code listID="Production Order Status">Released</Code>
<EffectiveDateTime>2013-11-13T10:45:51Z</EffectiveDateTime>
</Status>
<BillOfResources>
<Operations>
<ID>10</ID>
<NextID>20</NextID>
<Note/>
<Status>
<Code listID="Production Order Status">Planned</Code>
<EffectiveDateTime>2013-11-13T10:45:51Z</EffectiveDateTime>
</Status>
<ConsumedItem>
<ItemID>
<ID>BL_BLU</ID>
</ItemID>
<Description>Gehäuse blau</Description>
<LineNumber>10</LineNumber>
<Quantity unitCode="ST">1</Quantity>
<BaseUOMQuantity unitCode="ST">1</BaseUOMQuantity>
<Location type="Warehouse">
<ID>W_RM</ID>
</Location>
</ConsumedItem>
<ConsumedItem>
<ItemID>
<ID>BL_INC</ID>
</ItemID>
<Description>Glühlampe</Description>
<LineNumber>20</LineNumber>
<Quantity unitCode="ST">3</Quantity>
<BaseUOMQuantity unitCode="ST">3</BaseUOMQuantity>
<Location type="Warehouse">
<ID>W_RM</ID>
</Location>
</ConsumedItem>
</Operations>
<Operations>
<ID>20</ID>
<Note/>
<Status>
<Code listID="Production Order Status">Planned</Code>
<EffectiveDateTime>2013-11-13T10:45:51Z</EffectiveDateTime>
</Status>
<OutputItem>
<ItemID>
<ID>BIKELIGHT_RAC_BLU_INC_3_MET_I</ID>
</ItemID>
<Description>Bikelight Modell Racer</Description>
<Location type="Warehouse">
<ID>W_FWB</ID>
</Location>
</OutputItem>
</Operations>
</BillOfResources>
</ProductionOrderDetail>
</ProductionOrder>
</DataArea>
[...]
1.
已发布
2013-11-13T10:45:51Z
10
20
计划的生产订单状态
2013-11-13T10:45:51Z
布鲁
盖乌斯布劳
10
1.
1.
W_RM
布鲁公司
格鲁兰佩
20
3.
3.
W_RM
20
计划的生产订单状态
2013-11-13T10:45:51Z
BIKELIGHT\u RAC\u BLU\u INC\u 3\u MET\u I
Bikelight Modell赛车手
W_FWB
问题出现在第二分钟内
FETCH NEXT FROM db_cursor INTO @bom_id, @stock_id, @operation_id, @article_description, @line_number, @quantity
而光标的顺序是bom\u id、操作\u id、库存\u id(…),因此库存\u id映射到操作\u id,反之亦然
感谢这个问题的所有读者。首先,为了避免重复代码和可能出现的错误,我建议使用如下光标结构:
declare db_cursor cursor for
select ...
open db_cursor
while 1 = 1
begin
fetch db_cursor into @variable
if @@fetch_status <> 0
break
...
end
close db_cursor
deallocate db_cursor
merge table1 as t
using (
select
a.b.value('key1[1]', 'int') as key1,
a.b.value('val1[1]', 'int') as val1,
a.b.value('val2[1]', 'int') as val2
from @xmlData.nodes('root/data') as a(b)
) as x on x.key1 = t.key1
when matched then
update set
val1 = x.val1,
val2 = x.val2
when not matched then
insert (key1, val1, val2)
values (x.key1, x.val1, x.val2);
感谢您的回复和建设性的评论。我会试试你的第一个建议。关于你的第二句话-我可能有n个操作发生,所以我认为需要一个游标来遍历xml中的n个操作节点,我这里有什么错误吗?@osterhase没有,你可以插入/更新n行。事实上,这是首选的SQL方法-尝试谷歌RBAR,例如这一个-再次感谢-你甚至为我谷歌了一篇很棒的文章。:)还有很多东西要学。。。干杯。您的第二个代码示例包含语法错误,我无法修复它。也许你能帮我一下?@osterhase更新了示例,并提供了sql fiddle演示,很抱歉出现语法错误