【问题标题】:Iterate through XML variable in SQL Server遍历 SQL Server 中的 XML 变量
【发布时间】:2013-05-11 16:20:06
【问题描述】:

我在存储过程(SQL Server 2008)中有一个 XML 变量,它的示例值为

<parent_node>
   <category>Low</category>
   <category>Medium</category>
   <category>High</category>
</parent_node>

我必须将每个类别作为单独的记录插入表中。如何在 XML 中迭代并获取单个节点值?

如果我想调用一个存储过程并将每个类别作为输入参数发送,我们该怎么做?存储过程是遗留过程,它一次只接受一个类别。我正在尝试以这种方式调用过程。

  1. 循环从 xml 变量中获取单个类别。
  2. 使用当前类别调用存储过程。
  3. 移至下一个类别。
  4. 循环直到列表包含值。

任何帮助将不胜感激。

【问题讨论】:

  • 反对的选民请添加评论。这会有所帮助。

标签: sql sql-server xml sql-server-2008


【解决方案1】:

这样的?

DECLARE @XmlVariable XML = '<parent_node>
                              <category>Low</category>
                              <category>Medium</category>
                              <category>High</category>
                            </parent_node>'

INSERT INTO dbo.YourTargetTable(CategoryColumn)
  SELECT 
     XTbl.Cats.value('.', 'varchar(50)')
  FROM 
     @XmlVariable.nodes('/parent_node/category') AS XTbl(Cats)

更新:如果您必须使用旧的旧存储过程并且无法更改它(这是我的首选方式),那么您将不得不这样做逐行痛苦(RBAR)循环自己,例如通过使用表变量:

-- declare temporary work table
DECLARE @RbarTable TABLE (CategoryName VARCHAR(50))

-- insert values into temporary work table
INSERT INTO @RbarTable(CategoryName)
  SELECT 
     XTbl.Cats.value('.', 'varchar(50)')
  FROM 
     @XmlVariable.nodes('/parent_node/category') AS XTbl(Cats)

-- declare a single category
DECLARE @CategoryNameToBeInserted VARCHAR(50)

-- get the first category
SELECT TOP 1 @CategoryNameToBeInserted = CategoryName FROM @RbarTable

-- as long as we have data
WHILE @CategoryNameToBeInserted IS NOT NULL
BEGIN
    -- execute your stored procedure here.....    
    EXEC sp_executesql N'dbo.YourStoredProcedure @CategoryName', 
                       N'@CategoryName VARCHAR(50)', 
                       @CategoryName = @CategoryNameToBeInserted

    -- delete the category we just inserted from the temporary work table
    DELETE FROM @RbarTable WHERE CategoryName = @CategoryNameToBeInserted

    -- see if we still have more categories to insert    
    SET @CategoryNameToBeInserted = NULL
    SELECT TOP 1 @CategoryNameToBeInserted = CategoryName FROM @RbarTable ORDER BY CategoryName
END

【讨论】:

  • 谢谢。一个小小的疑问。如果我想调用存储过程并将每个类别作为输入参数发送。我们怎么能做到这一点。存储过程是遗留过程,它一次只接受一个类别。我正在尝试以这种方式。循环从 xml 变量中获取单个类别调用具有当前类别的存储过程移动到下一个类别循环,直到列表包含值您对获取单个类别有任何想法。
  • @iamsumesh:你不能轻易做到这一点。 T-SQL 基于集合 - 它不太适合“遍历项目列表并为每一行调用存储过程”。如果你有这个 --> 你最好在你的前端代码(C#,PHP - 不管)中这样做。在 T-SQL 中,您最好重写您的存储过程以将单个 XML 作为参数并在其中包含一个 INSERT 语句。..
  • 旧存储过程正在从另一个存储过程调用。我无权访问前端代码和遗留存储过程代码。从前端应用程序中,我们得到一个包含类别的 xml 变量。前端将调用我的存储过程,该存储过程将根据 xml 变量中的类别数多次调用旧存储过程。有什么建议可以实现这一目标?
  • @iamsumesh:请注意:这是一个 stored 过程 - 就像在 SQL Server 中的 stored 中一样 - 它与“存储”无关" ....
  • 我怎样才能在这里用我的问题实现同样的目标:stackoverflow.com/questions/26426412/…
【解决方案2】:

在 SQL Server 中使用 XML 总是有不止一种方法可以做到这一点。根据您的 XML 文档的大小和查询它的次数,您最好使用 sp_xml_preparedocument 来解析文档,为您提供引用它的句柄,然后您可以多次查询它和你想要的方式。这样做的方法如下:

declare @xml xml = '
<parent_node>
   <category>Low</category>
   <category>Medium</category>
   <category>High</category>
</parent_node>'
declare @xml_handle int

exec sp_xml_preparedocument @xml_handle output, @xml

select value from openxml(@xml_handle, '/parent_node/category', 2) with (value varchar(100) 'text()') x

exec sp_xml_removedocument @xml_handle

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多