2015-11-09 223 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所需的数据水平和插入的行,那么一个新的水平等等...

祝你好运!