4

我有这个 xml 结构。我使用以下 sql 来读取值,但它不起作用

DECLARE @x XML =
'<Events>
  <Event DateTimeGMT="25/10/2013 18:45:00" Branch="Soccer" Sport="Soccer" BranchID="1" League="England - Championship" LeagueID="10099" ID="5693075" IsOption="0" EventType="0" MEID="2673883">
    <Participants>
      <Participant1 Name="Middlesbrough" Home_Visiting="Home" />
      <Participant2 Name="Doncaster" Home_Visiting="Visiting" />
    </Participants>
    <MoneyLine Home="1.69" Draw="3.7" Away="5" />
    <Spread Home_Odds="1.885" Home_Points="-0.75" Away_Points="0.75" Away_Odds="1.962" />
    <Total Points="2.75" Over="2.06" Under="1.763" />
  </Event>
  <Event DateTimeGMT="25/10/2013 18:45:00" Branch="Soccer" Sport="Soccer" BranchID="1" League="England - Championship" LeagueID="10099" ID="5693993" IsOption="1" EventType="200" MEID="2673883">
    <Participants>
      <Participant1 Name="Middlesbrough" Home_Visiting="Home" />
      <Participant2 Name="Doncaster" Home_Visiting="Visiting" />
    </Participants>
    <Total Points="4.5" Over="5.75" Under="1.125" />
  </Event>
</Events>
'
DECLARE @iDoc INT
EXECUTE sp_xml_preparedocument @iDoc OUTPUT, @x

SELECT  *
FROM    OPENXML(@iDoc,'/Events/Event')
WITH    (
ID int '@ID',
DateTimeGMT [varchar](100) '@DateTimeGMT',
Branch [varchar](100) '@Branch',
Sport [varchar](100) '@Sport',
BranchID int '@BranchID',
League [varchar](100) '@League',
LeagueID int '@LeagueID',
IsOption int '@IsOption',
EventType int '@EventType',
MEID int '@MEID',
QAID int '@QAID',
EventName [varchar](500) '@EventName',
Home [varchar](100) '../Event/Participants/Participant1/@Name',
Away [varchar](100) '../Event/Participants/Participant2/@Name',
[1] [varchar](5) '../Event/MoneyLine/@Home',
[X] [varchar](5) '../Event/MoneyLine/@Draw',
[2] [varchar](5) '../Event/MoneyLine/@Away',
Spread_Home_Points float '../Event/Spread/@Home_Points',
Spread_Home_Odds float '../Event/Spread/@Home_Odds',
Spread_Away_Points float '../Event/Spread/@Away_Points',
Spread_Away_Odds float '../Event/Spread/@Away_Odds',
Total_Points float '../Event/Total/@Points',
Lart float '../Event/Total/@Over',
Posht float '../Event/Total/@Under'
        )

EXECUTE sp_xml_removedocument @iDoc

但这并没有给出正确的答案。在第二行没有很好的 MoneyLine 上,它重复第一行的值。 在此处输入图像描述

标有圆圈的值显示为空。请帮助?

4

3 回答 3

3

Event您使用的 XPath 表达式与您所追求的元素不匹配。仅考虑和列1,它们的 XPath 表达式应该是:X2

[1] [varchar](5) 'MoneyLine/@Home',
[X] [varchar](5) 'MoneyLine/@Draw',
[2] [varchar](5) 'MoneyLine/@Away',

这样,它们将与Event您正在考虑的元素相关。使用您的原始表达式,他们指向Event正在处理的行的父级的第一个元素,这就是他们行为错误的原因。相同的注意事项适用于以 . 开头的代码块中的所有其他表达式../Event

于 2013-10-26T08:57:03.893 回答
2

我建议使用 nodes() 方法在 SQL server 中读取 xml,它更容易使用。对于您的 XML,它可能是这样的:

select
    T.C.value('@DateTimeGMT', 'varchar(100)') as DateTimeGMT,
    T.C.value('@Branch', 'varchar(100)') as Branch,
    T.C.value('@BranchID', 'int') as BranchID,
    T.C.value('@League', 'varchar(100)') as League,
    T.C.value('@LeagueID', 'int') as LeagueID,
    T.C.value('@IsOption', 'int') as IsOption,
    T.C.value('@EventType', 'int') as EventType,
    T.C.value('@MEID', 'int') as MEID,
    T.C.value('@QAID', 'int') as QAID,
    T.C.value('@EventName', 'varchar(500)') as EventName,
    T.C.value('(Participants/Participant1)[1]/@Name', 'varchar(100)') as Home,
    T.C.value('(Participants/Participant2)[1]/@Name', 'varchar(100)') as Away,
    T.C.value('(MoneyLine)[1]/@Home', 'varchar(5)') as [1],
    T.C.value('(MoneyLine)[1]/@Draw', 'varchar(5)') as [X],
    T.C.value('(MoneyLine)[1]/@Away', 'varchar(5)') as [2],
    T.C.value('(Spread)[1]/@Home_Points', 'float') as Spread_Home_Points,
    T.C.value('(Spread)[1]/@Home_Odds', 'float') as Spread_Home_Odds,
    T.C.value('(Spread)[1]/@Away_Points', 'float') as Spread_Away_Points,
    T.C.value('(Spread)[1]/@Away_Odds', 'float') as Spread_Away_Odds,
    T.C.value('(Spread)[1]/@Away_Odds', 'float') as Spread_Away_Odds,
    T.C.value('(Total)[1]/@Points', 'float') as Total_Points,
    T.C.value('(Total)[1]/@Over', 'float') as Lart,
    T.C.value('(Total)[1]/@Under', 'float') as Posht
from @x.nodes('Events/Event') as T(C)

sql fiddle demo

要从按属性过滤的元素中获取数据,可以使用 xpath:

select
    T.C.value('(Participants/Participant[@Name="Odd"]/Odds)[1]/@OddsValue', 'float') as Odd,
    T.C.value('(Participants/Participant[@Name="Even"]/Odds)[1]/@OddsValue', 'float') as Even
from @x.nodes('Events/Event') as T(C)

sql fiddle demo

于 2013-10-26T11:53:15.703 回答
0

除了 Efran 的回答 (+1) 我会使用nodesvalue方法 ( ref ) 来查询 XML:

SELECT  x.XmlCol.value('(@ID)[1]', 'INT') AS [ID],
        x.XmlCol.value('(@DateTimeGMT)[1]', '[varchar](100)') AS [DateTimeGMT],
        x.XmlCol.value('(Sport)[1]', '[varchar](100)') AS [Sport],
        -- ...
        x.XmlCol.value('(Participants/Participant1/@Name)[1]', '[varchar](100)') AS [Home],
        x.XmlCol.value('(Participants/Participant2/@Name)[1]', '[varchar](100)') AS [Away],
        -- ...
        x.XmlCol.value('(MoneyLine/@Home)[1]', '[varchar](5)') AS [1],
        x.XmlCol.value('(MoneyLine/@Draw)[1]', '[varchar](5)') AS [X],
        x.XmlCol.value('(MoneyLine/@Away)[1]', '[varchar](5)') AS [2]
FROM    @x.nodes('/Events/Event') x(XmlCol);
于 2013-10-26T09:13:09.913 回答