2013-10-26 2 views
4

У меня есть этот XML structure.I использовать следующий SQL, чтобы считывать значения, но он не работаетсинтаксического анализа XML в SQL Server

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 

Но это doent дать правильный ответ. Во второй строке, которая не отличает MoneyLine, она повторяет первые значения строк. enter image description here

Значения, обозначенные знаком круга, пусты. Любая помощь, пожалуйста?

+0

Вы можете сделать вывод доступным для чтения/просмотра/больше? –

+0

Я немного порезал картинку – user1361208

ответ

2

Я предлагаю использовать узлы() метод для чтения XML в сервере SQL, это гораздо проще в использовании. Для вашего 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

+0

Да, это работает нормально, но если вы видите мой второй ответ, когда я добавляю другой узел, я не могу получить все параметры там. Пожалуйста, проверьте мой второй ответ – user1361208

+0

@ user1361208 не знаете, что именно вы хотите. Обновленный ответ, чтобы показать, как вы можете фильтровать xml по значению атрибута. Ответил на ваш другой вопрос другим способом анализа - все участники строк –

3

Выражения XPath, которые вы используете, не соответствуют элементу Event, который вы используете. Учитывая только колонны 1, X и 2, их XPath выражение должно быть:

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

Таким образом, они будут относительно Event элемента, который вы рассматриваете. С вашими оригинальными выражениями они указали на первый элемент Event родителя обрабатываемой строки, и именно поэтому они вели себя неправильно. Те же соображения применимы к любому другому выражению в вашем блоке кода, начиная с ../Event.

+0

Можете ли вы помочь с моим новым xml? – user1361208

0

Помимо ответа Efran в (+1) Я использовал бы nodes и value методы (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);