简体   繁体   English

如何使用SQL Cross Apply和MERGE

[英]How to use a SQL Cross Apply and a MERGE

Is there a way to use a Cross Apply with a MERGE statement? 有没有办法使用带有MERGE语句的Cross Apply I'm new to Cross Apply and still trying to figure all of it's tricks out. 我是Cross Apply新手,仍然试图解决所有这些问题。 Here's a mock demonstration of my INSERT and UPDATE that I'm doing on a cell that contains XML nodes: 这是我在包含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)

This is the content from my XML File: 这是我的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>

Where I get stuck on the MERGE statement is where to put the cross apply in the 'USING' section: 如果我被困在MERGE语句中,那么将交叉应用放在'USING'部分:

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

Thanks for your help! 谢谢你的帮助!

Try wrapping the OldTable as a Select statement in your Using . 尝试包裹OldTable作为Select在发言Using For example: 例如:

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

The XML bit seems weird to me, but I really don't know as much about XML in SQL as I should. XML对我来说似乎很奇怪,但我真的不太了解SQL中的XML。 However, this should point you in the right direction. 但是,这应该指向正确的方向。

All that you would need to add to the Merge statement are what you're doing When Matched or When Not Matched . 您需要添加到Merge语句中的所有内容都是您When MatchedWhen Not Matched

Using the fields in your original query, it would look like this: 使用原始查询中的字段,它将如下所示:

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)
;

Are you certain the syntax is correct on the cross apply? 您确定交叉申请的语法是否正确? I think it should be written as: 我认为应该写成:

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

I have never used cross apply with merge or XML like that before but I would wonder if this fixes it. 我从来没有像以前那样使用过合并或XML的交叉应用,但我想知道这是否能修复它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM