【问题标题】:Declaring a cursor with XML Namespaces (SQL Server 2012)使用 XML 命名空间声明游标 (SQL Server 2012)
【发布时间】:2015-08-24 17:37:10
【问题描述】:

我有一个默认命名空间 urn:iso:std:iso:20022:tech:xsd:camt.053.001.02 的 XML 文档,我相信我需要使用游标来遍历重复的段。

这是一个非常简化的文件版本:

<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
  <BkToCstmrStmt>
    <GrpHdr>...</GrpHdr>
    <Stmt>
      <Id>1</Id>
      <CreDtTm>2015-06-23T03:25:08.688+01:00</CreDtTm>
    </Stmt>
    <Stmt>
      <Id>2</Id>
      <CreDtTm>2015-06-23T03:25:09.000+01:00</CreDtTm>
    </Stmt>
    <Stmt>
      <Id>3</Id>
      <CreDtTm>2015-06-23T03:25:10.051+01:00</CreDtTm>
    </Stmt>
  </BkToCstmrStmt>
</Document>

我正在根据SQL 2012 - iterate through an XML list (better alternative to a WHILE loop) 这个答案中给出的建议。

如果没有默认的xmlns,我将能够声明一个游标来遍历stmt 部分,如下所示:

declare c cursor fast_forward for
select
    s.c.value('(Id/text())[1]', 'integer') as Id,
    s.c.value('(CreDtTm/text())[1]', 'datetime2(3)') as CreDtTm
from @XML_In.nodes('Document/BkToCstmrStmt') as b(c)
    outer apply b.c.nodes('Stmt') as s(c)

将返回此结果集:

Id  CreDtTm
1   2015-06-23 02:25:08.688
2   2015-06-23 02:25:09.000
3   2015-06-23 02:25:10.051

如果我使用的是普通的 select 语句,我可以像这样声明查询的默认命名空间(假设 @XML_In 是表示 XML 文档的字符串):

with xmlnamespaces(default 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02')
select
    s.c.value('(Id/text())[1]', 'integer') as Id,
    s.c.value('(CreDtTm/text())[1]', 'datetime2(3)') as CreDtTm
from @XML_In.nodes('Document/BkToCstmrStmt') as b(c)
    outer apply b.c.nodes('Stmt') as s(c)

如何将游标的使用与在显式默认命名空间中查询的需要结合起来?

【问题讨论】:

    标签: sql-server xml cursor xml-namespaces


    【解决方案1】:

    以您的链接问题为例,您是否尝试过将两者简单结合?

    DECLARE @XML_in XML = '<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
      <BkToCstmrStmt>
        <GrpHdr>...</GrpHdr>
        <Stmt>
          <Id>1</Id>
          <CreDtTm>2015-06-23T03:25:08.688+01:00</CreDtTm>
        </Stmt>
        <Stmt>
          <Id>2</Id>
          <CreDtTm>2015-06-23T03:25:09.000+01:00</CreDtTm>
        </Stmt>
        <Stmt>
          <Id>3</Id>
          <CreDtTm>2015-06-23T03:25:10.051+01:00</CreDtTm>
        </Stmt>
      </BkToCstmrStmt>
    </Document>'
    
    
    DECLARE cur CURSOR FAST_FORWARD
    FOR
    with xmlnamespaces(default 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02')
    SELECT s.c.value('(Id/text())[1]', 'integer') AS Id
        ,s.c.value('(CreDtTm/text())[1]', 'datetime2(3)') AS CreDtTm
    FROM @XML_In.nodes('Document/BkToCstmrStmt') AS b(c)
    OUTER APPLY b.c.nodes('Stmt') AS s(c)
    
    declare @Id int
    declare @CreDtTm datetime2(3)
    OPEN cur
    
    WHILE 1 = 1
    BEGIN
        FETCH cur
        INTO @Id
            ,@CreDtTm
    
        IF @@fetch_status <> 0
            BREAK
        -- Do whatever you like with your cursor
        select @Id, @CreDtTm
    END
    
    CLOSE cur
    
    DEALLOCATE cur
    

    结果

    ----------- ---------------------------
    1           2015-06-23 02:25:08.688
    
    (1 row(s) affected)
    
    
    ----------- ---------------------------
    2           2015-06-23 02:25:09.000
    
    (1 row(s) affected)
    
    
    ----------- ---------------------------
    3           2015-06-23 02:25:10.051
    
    (1 row(s) affected)
    

    【讨论】:

    • 我确实尝试了两者的简单组合,但不是按照您提供的顺序。信不信由你,declare c cursor local fast_forward for with xmlnamespaces(default 'urn...') select...for with 部分看起来如此丑陋,我认为这不可能是正确的。谢谢。
    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多