#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, '')