【问题标题】:How to use a SQL Cross Apply and a MERGE如何使用 SQL 交叉应用和 MERGE
【发布时间】:2014-07-20 16:13:57
【问题描述】:

有没有办法将Cross ApplyMERGE 语句一起使用?我是Cross Apply 的新手,但仍在尝试找出所有技巧。这是我在包含 XML 节点的单元格上执行的 INSERT 和 UPDATE 的模拟演示:

UPDATE NewTable 
SET
    NewTable.ID = ID,
    NewTable.Title =  Parent.Elm.value('(Title)[1]', 'varchar(100)'),
    NewTable.[Description] = Parent.Elm.value('(Description)[1]', 'varchar(100)'),
    NewTable.ChildTitle = Child.Elm.value('(ChildTitle)[1]', 'varchar(100)'),
    NewTable.StartDate = Child.Elm.value('(StartDate)[1]', 'DATETIME'), 
    NewTable.EndDate = Child.Elm.value('(EndDate)[1]', 'DATETIME')

FROM OldTable
           cross apply
      xmlFieldData.nodes('/ParentElement') xp(parent)
           cross apply
      xp.parent.nodes('ChildElement') xc(child)
WHERE OldTable.ID = NewTable.ID

INSERT INTO NewTable(ID, Title, [Description], ChildTitle, StartDate, EndDate )
SELECT

    Parent.Elm.value('(Title)[1]', 'varchar(100)') AS 'Title',
    Parent.Elm.value('(Description)[1]', 'varchar(100)') AS 'Description',
    Child.Elm.value('(ChildTitle)[1]', 'varchar(100)') AS 'ChildTitle',
    Child.Elm.value('(StartDate)[1]', 'DATETIME') AS 'StartDate',
    Child.Elm.value('(EndDate)[1]', 'DATETIME') AS 'EndDate'

FROM OldTable
           cross apply
      xmlFieldData.nodes('/ParentElement') Parent(Elm)
           cross apply
      Parent.Elm.nodes('ChildElement') Child(Elm)

这是我的 XML 文件中的内容:

<ParentElement>
  <Title>parent1</Title>
  <Description />
  <ChildElement>
    <Title>Child 4</Title>
    <Description />
    <StartDate>2010-01-25T00:00:00</StartDate>
    <EndDate>2010-01-25T00:00:00</EndDate>
  </ChildElement>
  <ChildElement>
    <Title>Child1</Title>
    <Description />
    <StartDate>2010-01-25T00:00:00</StartDate>
    <EndDate>2010-01-25T00:00:00</EndDate>
  </ChildElement>
  <ChildElement>
    <Title>Child6</Title>
    <Description />
    <StartDate>2010-01-25T00:00:00</StartDate>
    <EndDate>2010-01-25T00:00:00</EndDate>
  </ChildElement>
</ParentElement>

我在 MERGE 语句中遇到的问题是将交叉应用放在“使用”部分的位置:

MERGE INTO NewTable AS NewTable
USING OldTable
    cross apply
         xmlFieldData.nodes('/ParentElement') xp(parent)
    cross apply
     xp.parent.nodes('ChildElement') xc(child)
    WHERE OldTable.ID = NewTable.ID AND Child.Elm.value('(ChildTitle)[1]', (100)') = ChildTitle

感谢您的帮助!

【问题讨论】:

    标签: sql sql-server xml merge


    【解决方案1】:

    尝试将OldTable 包装为Select 语句在您的Using 中。例如:

    Merge Into NewTable As Target
    Using
    (   
        Select      Fields
        From        OldTable
        Cross Apply xmlFieldData.nodes('/ParentElement') xp(parent)
        Cross Apply xp.parent.nodes('ChildElement') xc(child)
        Where       Child.Elm.value('(ChildTitle)[1]', (100)) = ChildTitle
    ) As Source On Source.ID = Target.ID
    

    XML 位对我来说似乎很奇怪,但我对 SQL 中的 XML 的了解并不多。但是,这应该会为您指明正确的方向。

    您需要添加到Merge 语句的所有内容就是您正在执行的When MatchedWhen Not Matched

    使用原始查询中的字段,它看起来像这样:

    Merge Into NewTable As Target
    Using
    (   
        Select      ID,
                    Parent.Elm.value('(Title)[1]', 'varchar(100)')          [Title],
                    Parent.Elm.value('(Description)[1]', 'varchar(100)')    [Description],
                    Child.Elm.value('(ChildTitle)[1]', 'varchar(100)')      [ChildTitle],
                    Child.Elm.value('(StartDate)[1]', 'DATETIME')           [StartDate], 
                    Child.Elm.value('(EndDate)[1]', 'DATETIME')             [EndDate]
        From        OldTable
        Cross Apply xmlFieldData.nodes('/ParentElement') xp(parent)
        Cross Apply xp.parent.nodes('ChildElement') xc(child)
    ) As Source On Source.ID = Target.ID And Source.ChildTitle = Target.ChildTitle
    When Matched Then
        Update
        Set     Title       = Source.Title,
                Description = Source.Description,
                StartDate   = Source.StartDate,
                EndDate     = Source.EndDate
    When Not Matched Then
        Insert  (ID, Title, Description, ChildTitle, StartDate, EndDate)
        Values  (Source.ID, Source.Title, Source.Description, Source.ChildTitle, Source.StartDate, Source.EndDate)
    ;
    

    【讨论】:

    • 谢谢,我试试看!感谢您的意见!
    • 西尤尔!你真棒!有效!太感谢了!!!我非常感谢您花时间写出各个步骤的外观!我将此标记为正确答案!我也想给你点赞,但我没有足够的声望!再次感谢!你让我的星期五! :)
    【解决方案2】:

    你确定交叉应用的语法是正确的吗?我觉得应该写成:

    CROSS APPLY (SELECT FieldName = xmlFieldData.nodes('/ParentElement') xp(parent)) p
    

    我以前从未像这样使用过合并或 XML 的交叉应用,但我想知道这是否可以解决问题。

    【讨论】:

    • 感谢您提供帮助 Kyle,我认为我的语法是正确的,因为它有效。但我可能是错的 - 就像我说的,我是合并和交叉应用的新手。您提供的这个更正是否应该在合并中进行? FieldName 代表什么?
    • 你在那里教了我一些东西,我不知道你可以使用那种语法。
    • 我不会在任何凯尔上引用我的话——我可能是错的!我对此很陌生,很容易让自己感到困惑!这是我正在做的一个模拟演示。由于隐私,我无法分享实际代码。所以你认为看起来很奇怪,可能是一个错误。很抱歉让您如此困惑!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 2021-07-05
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多