【问题标题】:Suggestions on Troubleshooting "FOR XML EXPLICIT" Msg 6833 "requires parent tags to be opened first" Error关于“FOR XML EXPLICIT”Msg 6833“需要先打开父标签”错误的建议
【发布时间】:2010-12-17 00:01:06
【问题描述】:

我继承了一个 1000 行的存储过程,它使用 FOR XML EXPLICIT 生成 XML。我的问题是它大部分时间都有效。在某些情况下,我会收到错误:

父标签 ID 2 不在 open 之中 标签。 FOR XML EXPLICIT 需要父级 标签首先打开。检查 结果集的排序。 编号:6833 严重性:16 状态:1

我需要有关如何解决此问题的想法。我需要找出嵌套失败的地方。这可能是没有发出父行但有子行的情况。更糟糕的是,这个问题只发生在我们的测试系统上,它可能缺少一些生产数据。问题是如何从数千行中找到它?

我确信不存在一个疯狂的想法:SQL Server 有一个算法用于确定行的顺序是否正确。如果有一个工具可以查看我的结果集(没有 FOR XML EXPLICIT)并找出问题所在,然后告诉我,那就太好了(如果不太可能)。

在没有这样的工具的情况下,我欢迎任何关于如何调试它的建议。 XML(当它工作时)有四级深度!


更新:感谢您迄今为止的所有回答。看起来这是一个错误编辑的存储过程的问题。用“/* /” cmets 注释掉了大段 - 当代码中已经有“/ */” cmets 时,它不能很好地工作......当我再次更新时我确定答案。

【问题讨论】:

    标签: sql-server xml for-xml-explicit


    【解决方案1】:

    一种可能的方法是实际删除 FOR XML EXPLICIT 部分并查看由您的 sql 语句生成的结果集。它将指示生成 xml 的嵌套,并希望将您引导到该问题。请参阅以下图片,该图片取自 MSDN 文档: http://msdn.microsoft.com/en-us/library/ms189068.aspx.


    编辑

    可能值得发布一个示例输出,但在图像中的示例中,如果任何带有 tag=3 的行的 Order!2!Id 为空,您将得到相同的错误。此列实际上是标记 = 2 的父行和标记 = 3 的子行之间的连接。如果您的数据如上所示,我认为您可以通过识别 parent=2 且 Order!2!Id 为空的行来有效地找到您的问题。

    或者,它可能是订购。在这种情况下,您可以以某种方式构建一个查询,以识别结果集中出现在 Tag = 2 行之前的任何 Parent = 2 行。


    编辑 2

    CREATE TABLE MyTable(
        Tag int,
        Parent int,
        SomeIdentifier int
    )   
    
    INSERT INTO MyTable VALUES (2, 1, 1) -- this row defined before parent
    INSERT INTO MyTable VALUES (1, null, 1)
    INSERT INTO MyTable VALUES (3, 2, 1)
    INSERT INTO MyTable VALUES (3, 2, 1)
    INSERT INTO MyTable VALUES (1, null, 2)
    INSERT INTO MyTable VALUES (2, 1, 2)
    INSERT INTO MyTable VALUES (3, 2, 2)
    INSERT INTO MyTable VALUES (3, 2, 2)
    INSERT INTO MyTable VALUES (1, null, 3)
    INSERT INTO MyTable VALUES (3, 2, 3) -- this is orphaned
    INSERT INTO MyTable VALUES (3, 2, 3) -- this is orphaned
    
    ;WITH myCte AS(
    SELECT   Tag
            ,Parent
            ,SomeIdentifier
            ,ROW_NUMBER() OVER (PARTITION BY SomeIdentifier ORDER BY(SELECT 0)) AS RowOrder
    FROM    MyTable   
    ) SELECT c1.Tag
            ,c1.Parent
            ,c1.SomeIdentifier
    FROM myCte c1 
    LEFT OUTER JOIN myCte c2 ON c2.SomeIdentifier = c1.SomeIdentifier AND c1.Parent = c2.Tag
    WHERE c1.Parent IS NOT NULL     --ignore root rows for now
    AND   (c1.RowOrder < c2.RowOrder    --out of order rows
            OR    
           c2.Tag IS NULL)      --orphaned rows
    

    【讨论】:

    • 在审查您的问题时,我看到您可能已经考虑过这一点,但也许您可以将结果集分组到唯一标识每个 xml 文档和父列的标识符上,看看您在哪里有任何Parent 计数小于 2 的条目(不包括根的 null)
    • @cpedros:是的,我确实尝试删除“for xml explicit”。您能否举例说明您的分组建议?
    • @John 很抱歉,我想分组的想法不起作用。您可能已经发现错误可能是由多种原因造成的。我在编辑中添加了一些想法...
    • @cpedros:如果您可以举一个查询示例,我可以使用它来查找乱序标签,那么我会将其标记为答案。即使不是针对标签顺序的特定查询,也只是指向如何在行序列重要的情况下进行查询的链接(即,将一行与前一行进行比较)
    • @John 你可以试试我所做的编辑。我很欣赏这在很大程度上取决于一些隐含的排序,我认为无法保证这些排序,但对于我使用的示例数据集,这是可行的。
    【解决方案2】:

    使用 FOR XML 时,结果集的顺序必须是父 xml 节点在其子节点之前(通常,XML 文件不应该依赖于排序;这应该使用 XSL 转换来执行)

    感兴趣的:The Art of XSD(免费电子书)

    你可能已经知道了:如果你有 XSD,你可以使用一个工具来验证 XML 与 XSD(或编写大约 10 行 C# 来完成):

    How To Validate an XML Document by Using DTD, XDR, or XSD in Visual C# .NET

    如果您有格式正确的 XML 示例,您可以使用 XSD.exe 生成 XSD。

    【讨论】:

    • 谢谢。问题只是 SELECT 查询失败,因为如果要根据行集构造 XML,那么 XML 的格式就不是很好。不幸的是,它没有说明行集中的 5,000 行中的哪一行会导致这个问题,并且它不会继续并生成非格式良好的 XML!
    【解决方案3】:

    我会将行集(没有 FOR XML 子句)转储到临时表中。然后,您应该能够在此表中执行孤儿搜索。

    如果您找不到任何孤儿,这往往表明您的排序存在问题(父在行集中,但出现在子之后)。但至少我们会将该问题的搜索空间减半 :-)

    【讨论】:

      【解决方案4】:

      我找到了其中一个问题的答案,并想分享一些我学到的经验教训。

      我采用了存储过程的内容,并对其进行了更改,以便将结果集插入到表变量中。第 1 课:确保您在表变量中获得正确的列类型 - 我花了数小时研究一个由于无意中将列类型从 varchar 更改为 int 引起的问题,这导致排序顺序发生变化,从而转移了问题。

      一旦我修复了我的表变量,我就可以做一些有用的查询,比如:

      SELECT TOP n *
      FROM @result
      ORDER BY <same order as original query>
      FOR XML EXPLICIT
      

      我认为我必须进行“二分搜索”来确定哪一行有问题。事实证明,问题出在前几行。

      第 2 级数据由查询形成,其中包括到查找表的内部连接。这会导致在查找列未映射时忽略整行。这并没有阻止发出相应的级别 3 和 4 行,因此导致了错误。

      使用 LEFT JOIN 进行查找解决了问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-30
        • 2010-09-05
        • 2012-08-12
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多