2015-11-09 434 views
1

我想寫一個存儲過程來從XML字符串中提取信息並使用它創建多個父子關係。我試圖將這個XML推入實際的數據庫表中。基本上,本地客戶端將發送一個XML文件到數據庫並將其存儲爲一個字符串。然後我需要從該字符串中提取信息並更新相應的表。如果這只是表A到表B,這不會太困難。我遇到的問題是需要從表A到表B到表C到表D到適用的地方。下面是一個示例XML:多親子插入

<RunRecordFile> 
    <Competition> 
     <Name>Daily</Name> 
     <StartDate>11/9/2015 12:40:07 AM</StartDate> 
     <Runs> 
      <Id>123</Id> 
      <Name>Daily Run</Name> 
      <RunDate>11/9/2015 12:40:07 AM</RunDate> 
      <CompetitionId>1</CompetitionId> 
      <RunRecords> 
       <Id>001</Id> 
       <Number>007</Number> 
       <ElapsedTime>23.007</ElapsedTime> 
       <RunId>123</RunId> 
      </RunRecords> 
     </Runs> 
     <Runs> 
      <Id>456</Id> 
      <Name>Daily Run</Name> 
      <RunDate>11/9/2015 12:47:07 AM</RunDate> 
      <CompetitionId>1</CompetitionId> 
      <RunRecords> 
       <Id>002</Id> 
       <Number>700</Number> 
       <ElapsedTime>23.707</ElapsedTime> 
       <RunId>456</RunId> 
       <RunRecordSpecialty> 
        <Id>1</Id> 
        <Handicap>17</Handicap> 
        <TeamPoints>50000</TeamPoints> 
        <RunRecordId>002</RunRecordId> 
       </RunRecordSpecialty> 
      </RunRecords> 
     </Runs> 
    </Competition> 
</RunRecordFile> 

我已經嘗試使用聲明的表來保存每個創建的主鍵並使用SQL OUTPUT以收集那些。當我運行我的SQL時,我得到(0)行更新。下面是我在SQL已經試過:

CREATE PROC [dbo].[RaceFilePush] 
AS 
DECLARE @CompetitionIdMapping TABLE (CompetitionId bigint) 
DECLARE @RunIdMapping TABLE (RunId bigint) 
DECLARE @RunRecordIdMapping TABLE (RunRecordId bigint) 
BEGIN 
    DECLARE @rrXML AS XML 
    DECLARE @rrfId AS BIGINT 

    SET @rrfId = (SELECT TOP 1 Id FROM RunRecordFile WHERE Submitted IS NULL) 
    SET @rrXML = (SELECT TOP 1 RaceFile FROM RunRecordFile WHERE Id = @rrfId) 

    BEGIN TRAN Competitions 
    BEGIN TRY 

     INSERT INTO Competition (
      Name 
      ,StartDate 
     ) 
     OUTPUT INSERTED.Id INTO @CompetitionIdMapping(CompetitionId) 
     SELECT 
      xCompetition.value('(Name)[1]', 'varchar(225)') AS Name 
      ,xCompetition.value('(StartDate)[1]', 'datetime') AS StartDate 
      ,@rrfId AS RunRecordFileId 
     FROM 
      @rrXML.nodes('/RunRecordFile/Competition') AS E(xCompetition) 

     INSERT INTO Run (
      Name 
      ,RunDate 
      ,CompetitionId 
     ) 
     OUTPUT INSERTED.Id INTO @RunIdMapping(RunId) 
     SELECT 
      xRuns.value('(Name)[1]','varchar(80)') AS Name 
      ,xRuns.value('(RunDate)[1]','datetime') AS RunDate 
      ,(SELECT CompetitionId FROM @CompetitionIdMapping) 
     FROM 
      @rrXML.nodes('/RunRecordFile/Competition/Runs') AS E(xRuns) 

     INSERT INTO RunRecord (
      Number 
      ,ElapsedTime 
      ,RunId 
     ) 
     OUTPUT INSERTED.Id INTO @RunRecordIdMapping(RunRecordId) 
     SELECT 
      xRunRecords.value('(Number)[1]','varchar(10)') AS Number 
      ,xRunRecords.value('(ElapsedTime)[1]','numeric(10,5)') AS ElapsedTime 
      ,(SELECT RunId FROM @RunIdMapping) 
     FROM 
      @rrXML.nodes('/RunRecordFile/Competition/Runs/RunRecords') AS E(xRunRecords) 

     INSERT INTO RunRecordSpecialty (
      Handicap 
      ,TeamPoints 
      ,RunRecordId 
     ) 
     SELECT 
      xRunRecordSpecialty.value('(Handicap)[1]','numeric(10,5)') AS Handicap 
      ,xRunRecordSpecialty.value('(TeamPoints)[1]','numeric(10,5)') AS TeamPoints 
      ,(SELECT RunRecordId FROM @RunRecordIdMapping) 
     FROM 
      @rrXML.nodes('/RunRecordFile/Competition/Runs/RunRecordSpecialty') AS E(xRunRecordSpecialty) 

     UPDATE RunRecordFile SET Submitted = GETDATE() WHERE Id = @rrfId 

    COMMIT TRAN Competitions 
    END TRY 
    BEGIN CATCH 
     ROLLBACK TRAN Competitions 
    END CATCH 
END 
+0

嗨,剛纔看到你在附近......看來,你還是無法解決你的問題呢......你需要進一步的幫助嗎? – Shnugo

回答

0

有了這個SQL你整個事情成扁平聲明表@tbl

備註:我把XML從你的問題到一個名爲@xml變量。這適應你的需要......

DECLARE @tbl TABLE (
    [Competition_Name] [varchar](max) NULL, 
    [Competition_StartDate] [datetime] NULL, 
    [Run_Id] [int] NULL, 
    [Run_Name] [varchar](max) NULL, 
    [Run_RunDate] [datetime] NULL, 
    [Run_CompetitionId] [int] NULL, 
    [RunRecords_Id] [int] NULL, 
    [RunRecords_Number] [int] NULL, 
    [RunRecords_ElapsedTime] [float] NULL, 
    [RunRecords_RunId] [int] NULL, 
    [RunRecordSpecialty_Id] [int] NULL, 
    [RunRecordSpecialty_Handicap] [int] NULL, 
    [RunRecordSpecialty_TeamPoints] [int] NULL, 
    [RunRecordSpecialty_RunRecordId] [int] NULL 
); 

INSERT INTO @tbl 
SELECT Competition.value('Name[1]','varchar(max)') AS Competition_Name 
     ,Competition.value('StartDate[1]','datetime') AS Competition_StartDate 

     ,Run.value('Id[1]','int') AS Run_Id 
     ,Run.value('Name[1]','varchar(max)') AS Run_Name 
     ,Run.value('RunDate[1]','datetime') AS Run_RunDate 
     ,Run.value('CompetitionId[1]','int') AS Run_CompetitionId 

     ,RunRecords.value('Id[1]','int') AS RunRecords_Id 
     ,RunRecords.value('Number[1]','int') AS RunRecords_Number 
     ,RunRecords.value('ElapsedTime[1]','float') AS RunRecords_ElapsedTime 
     ,RunRecords.value('RunId[1]','int') AS RunRecords_RunId 

     ,RunRecordSpecialty.value('Id[1]','int') AS RunRecordSpecialty_Id 
     ,RunRecordSpecialty.value('Handicap[1]','int') AS RunRecordSpecialty_Handicap 
     ,RunRecordSpecialty.value('TeamPoints[1]','int') AS RunRecordSpecialty_TeamPoints 
     ,RunRecordSpecialty.value('RunRecordId[1]','int') AS RunRecordSpecialty_RunRecordId 

FROM @xml.nodes('/RunRecordFile/Competition') AS A(Competition) 
OUTER APPLY Competition.nodes('Runs') AS B(Run) 
OUTER APPLY Run.nodes('RunRecords') AS C(RunRecords) 
OUTER APPLY RunRecords.nodes('RunRecordSpecialty') AS D(RunRecordSpecialty) 
; 
SELECT * FROM @tbl 

如果你需要生成的ID,你只需要添加的列@tbl並寫有,「開流」或室內用後聲明UPDATE

它應該很容易通過這個平臺的工作,選擇剛剛與DISTINCT所需的數據水平和插入的行,那麼一個新的水平等等...

祝你好運!