通过XML多记录到存储过程

时间:2016-04-07 15:32:09

标签: sql sql-server xml stored-procedures sql-update

我希望将以下XML作为字符串传递给SQL,并根据UPDATEEventID标识的现有表列将目标表行GROUP传递给.....

<Item>
    <GroupItem>
        <Group1>A</Group1>
        <Price>100</Price>
        <Location>Here</Location>
    </GroupItem>

    <GroupItem>
        <Group2>B</Group2>
        <Price>200</Price>
        <Location>There</Location>
    </GroupItem>

    <GroupItem>
        <Group3>C</Group3>
        <Price>300</Price>
        <Location>Everywhere</Location>
    </GroupItem>

    <EVENTID>12345</EVENTID>
    <MATCHED>100</MATCHED>
</Item>

因此,在此示例中,我想要更新EventID为12345的表行,并为列提供值:GROUP1 = AGROUP2 = BGROUP3 = C ...

任何帮助解开我所处的混乱(再一次)都会感激......

TARGET TABLE结构如下:

CREATE TABLE [dbo].[GROUPTABLE](
[EventID] [int] NOT NULL,
[Group1A] [nvarchar](50) NULL,
[Group1B] [nvarchar](50) NULL,
[Group1C] [nvarchar](50) NULL,
[Group1D] [nvarchar](50) NULL,
[Group1_Location] [nvarchar](50) NULL,
[Group1_Matched] [float] NULL,
[Group2A] [nvarchar](50) NULL,
[Group2B] [nvarchar](50) NULL,
[Group2_Matched] [float] NULL,
[Group2_Location] [nvarchar](50) NULL,
[Group3A] [nvarchar](50) NULL,
[Group3B] [nvarchar](50) NULL,
[Group3_Matched] [float] NULL,
[Group3_Location] [nvarchar](50) NULL,
[Group4A] [nvarchar](50) NULL,
[Group4B] [nvarchar](50) NULL,
[Group4_Matched] [float] NULL,
[Group4_Location] [nvarchar](50) NULL,

CONSTRAINT [PK_GROUPTABLE] PRIMARY KEY CLUSTERED 
(
[EventID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

虽然这在概念上可能没有意义 - 这不是我在我的应用程序中使用的确切表 - (我不想放弃太多),但这种结构模仿了我想要做的事情&# 39,真正的&#39;表....

1 个答案:

答案 0 :(得分:0)

UPDATE2

只需将整个代码块复制到一个空的查询窗口中并尝试一下......

/*
This is your mimic table
Btw: It is - in almost all cases! - a very bad idea to store related data in a table like data1, data2, data3...
If possible you should introduce a table GroupValues with a foreign key onto group table
*/
CREATE TABLE [dbo].[GROUPTABLE](
[EventID] [int] NOT NULL,
[Group1A] [nvarchar](50) NULL,
[Group1B] [nvarchar](50) NULL,
[Group1_Matched] [float] NULL,
[Group1_Location] [nvarchar](50) NULL,
[Group2A] [nvarchar](50) NULL,
[Group2B] [nvarchar](50) NULL,
[Group2_Matched] [float] NULL,
[Group2_Location] [nvarchar](50) NULL,
[Group3A] [nvarchar](50) NULL,
[Group3B] [nvarchar](50) NULL,
[Group3_Matched] [float] NULL,
[Group3_Location] [nvarchar](50) NULL,
[Group4A] [nvarchar](50) NULL,
[Group4B] [nvarchar](50) NULL,
[Group4_Matched] [float] NULL,
[Group4_Location] [nvarchar](50) NULL,

CONSTRAINT [PK_GROUPTABLE] PRIMARY KEY CLUSTERED 
(
[EventID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

--here I insert two dummy rows
INSERT INTO GROUPTABLE VALUES
 (1,   'Gr1A','Gr1B',111,'Gr1Location'
      ,'Gr2A','Gr2B',222,'Gr2Location'
      ,'Gr3A','Gr3B',333,'Gr3Location'
      ,'Gr4A','Gr4B',444,'Gr4Location'
      )
,(12345,'Gr1A','Gr1B',111,'Gr1Location'
       ,'Gr2A','Gr2B',222,'Gr2Location'
       ,'Gr3A','Gr3B',333,'Gr3Location'
       ,'Gr4A','Gr4B',444,'Gr4Location'
      );

--one test to show the data
SELECT * FROM dbo.GROUPTABLE;

--Here's your XML
DECLARE @XML XML=
'<Item>
    <GroupItem>
        <Group1>A</Group1>
        <Price>100</Price>
        <Location>Here</Location>
    </GroupItem>

    <GroupItem>
        <Group2>B</Group2>
        <Price>200</Price>
        <Location>There</Location>
    </GroupItem>

    <GroupItem>
        <Group3>C</Group3>
        <Price>300</Price>
        <Location>Everywhere</Location>
    </GroupItem>

    <EVENTID>12345</EVENTID>
    <MATCHED>100</MATCHED>
</Item>';

/*
And this is the UPDATE
If necessary you might use .query() to get the nodes and save repeated XPath-navigation
Anyway: Much better was a 
<Item>
    <GroupItem group="A">
        <Group>A</Group>
        <Price>100</Price>
        ...
    <GroupItem group="B">
        <Group>A</Group>
        <Price>100</Price>
        ...
to avoid differint element names
*/

UPDATE dbo.GROUPTABLE
SET Group1A         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group1"])[1]','varchar(max)')
   ,Group2A         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group2"])[1]','varchar(max)')
   ,Group3A         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group3"])[1]','varchar(max)')
   ,Group4A         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group4"])[1]','varchar(max)')

   ,Group1B         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group1"]/../Price)[1]','varchar(max)')
   ,Group2B         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group2"]/../Price)[1]','varchar(max)')
   ,Group3B         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group3"]/../Price)[1]','varchar(max)')
   ,Group4B         = @XML.value('(/Item/GroupItem/*[local-name(.)="Group4"]/../Price)[1]','varchar(max)')

   ,Group1_Matched  = @XML.value('(/Item/MATCHED)[1]','float')
   ,Group2_Matched  = @XML.value('(/Item/MATCHED)[1]','float')
   ,Group3_Matched  = @XML.value('(/Item/MATCHED)[1]','float')
   ,Group4_Matched  = @XML.value('(/Item/MATCHED)[1]','float')

   ,Group1_Location = @XML.value('(/Item/GroupItem/*[local-name(.)="Group1"]/../Location)[1]','varchar(max)')
   ,Group2_Location = @XML.value('(/Item/GroupItem/*[local-name(.)="Group2"]/../Location)[1]','varchar(max)')
   ,Group3_Location = @XML.value('(/Item/GroupItem/*[local-name(.)="Group3"]/../Location)[1]','varchar(max)')
   ,Group4_Location = @XML.value('(/Item/GroupItem/*[local-name(.)="Group4"]/../Location)[1]','varchar(max)')

WHERE EventID=@XML.value('(/Item/EVENTID)[1]','int');

--Here you see, that the item' value changed for EventID=12345
SELECT * FROM dbo.GROUPTABLE;

--Clean Up
--DROP TABLE dbo.GROUPTABLE

更新

使用此查询,您可以一次性获取所有数据

SELECT @XML.value('(/Item/EVENTID)[1]','int') AS EventId
      ,@XML.value('(/Item/MATCHED)[1]','int') AS Matched
      ,A.B.value('local-name(*[position()=1][1])','varchar(max)') AS GroupName
      ,A.B.value('*[position()=1][1]','varchar(max)') AS FirstNode
      ,A.B.value('Price[1]','decimal(12,4)') AS Price
      ,A.B.value('Location[1]','varchar(max)') AS Location
FROM @XML.nodes('/Item/GroupItem') AS A(B)  

结果

12345   100 Group1  A   100.0000    Here
12345   100 Group2  B   200.0000    There
12345   100 Group3  C   300.0000    Everywhere

其实我怀疑你给出的描述真的是你想要的:-),但这是实现我理解的方法:

DECLARE @XML XML=
'<Item>
    <GroupItem>
        <Group1>A</Group1>
        <Price>100</Price>
        <Location>Here</Location>
    </GroupItem>

    <GroupItem>
        <Group2>B</Group2>
        <Price>200</Price>
        <Location>There</Location>
    </GroupItem>

    <GroupItem>
        <Group3>C</Group3>
        <Price>300</Price>
        <Location>Everywhere</Location>
    </GroupItem>

    <EVENTID>12345</EVENTID>
    <MATCHED>100</MATCHED>
</Item>';

声明一个表变量,用测试数据填充它

DECLARE @tbl TABLE(ID INT,Group1 VARCHAR(10),Group2 VARCHAR(10),Group3 VARCHAR(10));
INSERT INTO @tbl VALUES
 (3456,'Test1','Test2','Test3')
,(12345,'Test1','Test2','Test3');

SELECT * FROM @tbl;

结果

3456    Test1   Test2   Test3
12345   Test1   Test2   Test3

更改ID = 12345的行

UPDATE @tbl SET Group1 = @XML.value('(/Item/GroupItem/*[local-name(.)="Group1"])[1]','varchar(max)')
               ,Group2 = @XML.value('(/Item/GroupItem/*[local-name(.)="Group2"])[1]','varchar(max)')
               ,Group3 = @XML.value('(/Item/GroupItem/*[local-name(.)="Group3"])[1]','varchar(max)')
WHERE ID=@XML.value('(/Item/EVENTID)[1]','int');

结果

SELECT * FROM @tbl;

3456    Test1   Test2   Test3
12345   A       B       C