对于带有子查询和嵌套节点的SQL中的xml

时间:2015-04-02 14:53:41

标签: sql xml

所以我有一个触发器,可以使XML"事务"数据更改为客户端人口统计数据 它在大多数情况下工作,但我无法使节点结构非常正确 一个客户端最多可以拥有3个电话记录,我试图让每个电话记录都嵌入到一个客户端节点下,而不是重复整个客户端节点,同时使用带电话的subquerys会遇到一些麻烦

 --sample tables 
        DECLARE @phone TABLE ( MPIID int, phoneTypeNm VARCHAR(MAX), Phone VARCHAR(MAX), PhoneID int )
        DECLARE @province TABLE ( provinceID INT, provinceCd VARCHAR(MAX) )
        DECLARE @client TABLE ( FirstName VARCHAR(MAX), LastName VARCHAR(MAX), clientID INT )
        DECLARE @inserted TABLE ( provinceID int, address VARCHAR(MAX), addressid int, MPIID int )
        DECLARE @deleted TABLE ( provinceID int, address VARCHAR(MAX), addressid int, MPIID int )
        INSERT INTO @phone (MPIID, phoneTypeNm, Phone, PhoneID)
        VALUES
        (4 , 'School' , '123-4567', 123),
        (3 , 'Home' , '123-4567', 124),
        (3 , 'Work' , '765-4321', 2352),
        (1 , 'Cell' , '012-3654', 23672);
        INSERT INTO @province (provinceID, provinceCd)
        VALUES
        (1, 'ON'),
        (3, 'AB'),
        (4, 'PI'),
        (2, 'BC');
        INSERT INTO @client (FirstName, LastName, clientID)
        VALUES ('james', 'elroy', 1),
           ('andrew', 'lucy', 4),
           ('adam,', 'trevor', 3);
        INSERT INTO @inserted (provinceID, address, addressid, MPIID)
        VALUES  (2, '123 fake st', 11, 1),
            (4, '123 none st', 14, 4), 
            (1, '123 inserted st', 13, 3);
        INSERT INTO @deleted (provinceID, address, addressid, MPIID)
        VALUES (1, '123 old st', 11, 1),
           (4, '123 none st', 14, 4),
           (3, '123 deleted st', 12, 2);

下面的代码使xml的数据发生了变化,这将在触发器上运行以访问插入和删除的表

       DECLARE @NewTransaction XML;

    SET @NewTransaction = ( SELECT * FROM (
                 SELECT  
                 c.ClientID AS [@UniqueIdentifier]
                 ,[@Type] = CASE WHEN new.MPIID IN (SELECT new.MPIID FROM @inserted) THEN 'U' END
                 ,[FirstName] = CASE when new.MPIID = old.MPIID THEN NULL ELSE c.FirstName END
                 ,[LastName] = CASE when new.MPIID = old.MPIID THEN NULL ELSE c.LastName END
                 ,[Address/@UniqueIdentifier] = CASE when new.addressid = old.addressid THEN NULL ELSE new.addressid END
                 ,[Address/@Type] = CASE WHEN new.addressid IN (SELECT new.addressid FROM @inserted) THEN 'U' END
                 ,[Address/Street] = CASE when new.address = old.address THEN NULL ELSE new.address END
                 ,[Address/Province] = CASE when new.provinceID = old.provinceID THEN NULL ELSE p.provinceCd END

                 ,CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.PhoneID END AS [Phone/@UniqueIdentifier]
                 ,[Phone/@Type] = CASE WHEN new.MPIID IN (SELECT new.MPIID FROM @inserted) THEN 'U' END
                 ,[Phone/PhoneType] = CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.phoneTypeNm END
                 ,[Phone/PhoneValue] = CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.Phone END

                 FROM @inserted [new] 
                 LEFT JOIN @deleted [old] ON new.addressid = old.addressid 
                 LEFT JOIN @client [c] ON new.MPIID = c.clientID 
                 LEFT JOIN @phone [ph] ON new.MPIID = ph.MPIID
                 LEFT JOIN @province [p] ON new.provinceID = p.provinceID
                 UNION
                 SELECT MPIID, 'D',
                 NULL, NULL, NULL, NULL, NULL,
                 NULL, NULL, NULL, NULL, NULL
                 FROM @deleted
                 WHERE MPIID NOT IN (SELECT MPIID FROM @inserted) 

             ) AS temp FOR XML PATH('Client'), ROOT('Root'), TYPE, ELEMENTS)

             SELECT @NewTransaction

- 代码生成

    <Root>
  <Client UniqueIdentifier="433979" Type="U">
    <FirstName>Herwigaaa</FirstName>
    <LastName>Farm</LastName>
    <Address Type="U" UniqueIdentifier="357653">
      <Street>asddrdsslkdjf</Street>
      <Province>Qing</Province>
    </Address>
    <Phone Type="U">
      <PhoneType>Cellular</PhoneType>
      <PhoneValue>(166) 857-4648</PhoneValue>
    </Phone>
  </Client>
  <Client UniqueIdentifier="433979" Type="U">
    <FirstName>Herwigaaa</FirstName>
    <LastName>Farm</LastName>
    <Address Type="U" UniqueIdentifier="357653">
      <Street>asddrdsslkdjf</Street>
      <Province>Qing</Province>
    </Address>
    <Phone Type="U">
      <PhoneType>Home</PhoneType>
      <PhoneValue>(136) 371-8774</PhoneValue>
    </Phone>
  </Client>
    </Root>

我希望在

下面实现xml结构
<Root>
  <Client UniqueIdentifier="433979" Type="U">
    <FirstName>Herwigaaa</FirstName>
    <LastName>Farm</LastName>
    <Address Type="U" UniqueIdentifier="357653">
      <Street>asddrdsslkdjf</Street>
      <Province>Qing</Province>
    </Address>
    <Phone Type="U" UniqueIdentifier="124">
      <PhoneType>Cellular</PhoneType>
      <PhoneValue>(166) 857-4648</PhoneValue>
    </Phone>
    <Phone Type="U" UniqueIdentifier="2352">
        <PhoneType>Home</PhoneType>
        <PhoneValue>(136) 371-8774</PhoneValue>
    </Phone>
  </Client>
</Root>

1 个答案:

答案 0 :(得分:0)

       DECLARE @NewTransaction XML;

SET @NewTransaction = ( SELECT * FROM (
                 SELECT  
                 c.ClientID AS [@UniqueIdentifier]
                 ,[@Type] = CASE WHEN new.MPIID IN (SELECT new.MPIID FROM @inserted) AND new.MPIID IN (SELECT new.MPIID FROM @deleted) THEN 'U' END
                 ,[FirstName] = CASE when new.MPIID = old.MPIID THEN NULL ELSE c.FirstName END
                 ,[LastName] = CASE when new.MPIID = old.MPIID THEN NULL ELSE c.LastName END

                 ,[Addresses] = ( SELECT 
                  CASE when new.addressid = old.addressid THEN NULL ELSE new.addressid END AS [@UniqueIdentifier]
                 ,CASE WHEN new.addressid IN (SELECT new.addressid FROM @inserted) THEN 'U' END AS [@Type]
                 ,CASE when new.address = old.address THEN NULL ELSE new.address END AS [Street]
                 ,CASE when new.provinceID = old.provinceID THEN NULL ELSE p.provinceCd END AS [Province]
                 FROM @province p
                 WHERE new.provinceID = p.provinceID 
                 FOR XML PATH('Address'), TYPE, ELEMENTS )

                 ,[Phones] = ( SELECT 
                  CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.PhoneID END AS [@UniqueIdentifier]
                 ,CASE WHEN new.MPIID IN (SELECT new.MPIID FROM @inserted) THEN 'U' END AS [@Type]
                 ,CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.phoneTypeNm END AS [PhoneType]
                 ,CASE when new.MPIID = old.MPIID THEN NULL ELSE ph.Phone END AS [PhoneValue]
                 FROM @phone ph
                 WHERE new.MPIID = ph.MPIID 
                 FOR XML PATH('Phone'), TYPE, ELEMENTS ) 

                 FROM @inserted [new] 
                 LEFT JOIN @deleted [old] ON new.addressid = old.addressid 
                 LEFT JOIN @client [c] ON new.MPIID = c.clientID 
                 )AS temp
              FOR XML PATH('Client'), ROOT('Root'), TYPE, ELEMENTS)

               SELECT @NewTransaction

out put to

<Root>
  <Client UniqueIdentifier="3" Type="U">
    <FirstName>adam,</FirstName>
    <LastName>trevor</LastName>
    <Addresses>
      <Address UniqueIdentifier="13" Type="U">
        <Street>123 inserted st</Street>
        <Province>ON</Province>
      </Address>
    </Addresses>
    <Phones>
      <Phone UniqueIdentifier="124" Type="U">
        <PhoneType>Home</PhoneType>
        <PhoneValue>123-4567</PhoneValue>
      </Phone>
      <Phone UniqueIdentifier="2352" Type="U">
        <PhoneType>Work</PhoneType>
        <PhoneValue>765-4321</PhoneValue>
      </Phone>
    </Phones>
  </Client>
</Root>