SQL XML РАЗНИЦА в атрибутах

#sql #xml

#sql #xml

Вопрос:

У меня есть поле XML в таблице, и я хочу установить триггер для сохранения изменений в другой таблице. Я хочу знать, например, что атрибут «url» изменился с «http://example.com /» кому «http://newurl.com » и когда.

Это то, что у меня есть сейчас:

 DECLARE @XML1 XML
DECLARE @XML2 XML

SET @XML1 = 
'<NewDataSet> 
<Employee>
<EmpID>1005</EmpID>
<Name> keith </Name>
<DOB>12/02/1981</DOB>
<DeptID>ACC001</DeptID>
</Employee>
</NewDataSet>'

SET @XML2 = 
'<NewDataSet> 
<Employee>
<EmpID>1005</EmpID>
<Name> keith </Name>
<DOB>12/02/1981</DOB>
<DeptID>ACC002</DeptID>
</Employee>
</NewDataSet>'


;with XML1 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML1.nodes('/NewDataSet/Employee/*') as T(N)
),
XML2 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML2.nodes('/NewDataSet/Employee/*') as T(N)
)
select coalesce(XML1.NodeName, XML2.NodeName) as NodeName, 
       XML1.Value as OldVal, 
       XML2.Value as NewVal,
       GETUTCDATE() as changed
from XML1
  full outer join XML2
    on XML1.NodeName = XML2.NodeName
where coalesce(XML1.Value, '') <> coalesce(XML2.Value, '')  
 

Но это работает только для значений узлов, и я хочу, чтобы это работало и для атрибутов.

Пример XML-файла, в котором я хочу, чтобы он работал:

 <crawlsetup>
  <go param="" url="http://www.example.com/index.php">
    <match param="" match="href=amp;quot;(/job[^amp;quot;] )amp;quot;" url="http://www.example.com$1" save1="" save2="" save3="">
        <match param="" match="href=amp;quot;(/job[^amp;quot;] )amp;quot;" url="http://www.example.com$1" save1="" save2="" save3="" />
        <next match="" url="$1" />
    </match>
  </go>
</crawlsetup>
 

Может быть несколько атрибутов, и я хочу обнаружить изменения во всех атрибутах.

Может кто-нибудь помочь мне в этом? Спасибо =)

Ответ №1:

Если вы хотите выбрать только один атрибут (например, URL) элемента, используйте это выражение XPath :

 from @XML2.nodes('/crawlsetup/go/@url') as T(N)
 

Чтобы выбрать все атрибуты элемента, используйте этот :

 from @XML2.nodes('/crawlsetup/go/@*') as T(N)
 

Комментарии:

1. большое вам спасибо!! как насчет всех атрибутов всех элементов?

2. Пожалуйста. Чтобы выбрать все атрибуты всех узлов, обратитесь к ответу, предоставленному @Mikael Eriksson. Вы могли бы также взглянуть на [link] msdn.microsoft.com/en-us/library/vstudio /… для дальнейшего изучения выражений XPath, особенно раздела о путях к местоположению

3. PS: вы можете принять ответ, если он показался вам полезным

Ответ №2:

Используйте последовательность в функции nodes . Добавить /NewDataSet/Employee/@* .

 ;with XML1 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML1.nodes('/NewDataSet/Employee/*, /NewDataSet/Employee/@*') as T(N)
),
XML2 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML2.nodes('/NewDataSet/Employee/*, /NewDataSet/Employee/@*') as T(N)
)
select coalesce(XML1.NodeName, XML2.NodeName) as NodeName, 
       XML1.Value as OldVal, 
       XML2.Value as NewVal,
       GETUTCDATE() as changed
from XML1
  full outer join XML2
    on XML1.NodeName = XML2.NodeName
where coalesce(XML1.Value, '') <> coalesce(XML2.Value, '')