#tsql #sql-server-2008 #xquery-sql
#tsql #sql-server-2008 #xquery-sql
Вопрос:
Я столкнулся с проблемой при обновлении поля SQL в том, что то, что я написал, отлично работает для xml-узлов с присутствующим текстом, однако оно срабатывает, когда узел пуст.
<filemeta filetype="Video">
<heading>TEST</heading>
<description />
</filemeta>
Этот код работает нормально;
UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/heading/text())[1] with "TEST"');
Однако это нарушает;
UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/description/text())[1] with "notworking!"');
Спасибо за любую помощь.
Ответ №1:
Этот узел (/filemeta/description/text())[1]
не существует в XML, поэтому заменять нечего. Вместо этого вы должны выполнить вставку. Если у вас есть сценарий, в котором у вас есть сочетание пустых узлов и узлов со значением, вы должны выполнить две инструкции update .
declare @filemetaDB table(filemeta xml)
insert into @filemetaDB values
('<filemeta><description>Not empty</description></filemeta>'), -- Not empty node
('<filemeta><description/></filemeta>'), -- Empty node
('<filemeta></filemeta>') -- Missing node
-- Replace value for nodes with value
update @filemetaDB
set filemeta.modify('replace value of (/filemeta/description/text())[1] with "TEST 1"')
where filemeta.exist('/filemeta/description/text()') = 1
-- Add text node for empty nodes
update @filemetaDB
set filemeta.modify('insert text{"TEST 2"} into (/filemeta/description)[1]')
where filemeta.exist('/filemeta/description/text()') = 0
select *
from @filemetaDB
Результат:
filemeta
------------------------------------------------------
<filemeta><description>TEST 1</description></filemeta>
<filemeta><description>TEST 2</description></filemeta>
<filemeta />
Комментарии:
1. Как я могу использовать переменную в инструкции INSERT внутри метода modify?
2. @SiKni8 взгляните на использование sql: переменная(«»)
3. Попробовал это:
Set @xml.modify('insert xs:string(sql:variable("@locAnchor")) into (/root/StartOne/Value6)[1]');
Я продолжаю получать ошибку:XQuery [modify()]: Only non-document nodes can be inserted. Found "xs:string ?".
4. @SiKni8 Попробуйте это
set @xml.modify('insert text{sql:variable("@LocAnchor")} into (/root/StartOne/Value6)[1]');
5. Крайне неудачно. 🙂 Это все еще верно в 2018 году или были улучшения? Я не вижу в
replace
документах ничего, что указывало бы на то, что это было, но…
Ответ №2:
У меня был сценарий, в котором я хотел обновить ТОЛЬКО ПУСТЫЕ узлы.
UPDATE filemetaDB SET filemeta.modify('
insert text{"Oh, this works!!"}
into (/filemeta/description[not(node()) and not(text())])[1]
');
not (node()) означает отсутствие дочерних элементов, а not (text ()) означает отсутствие текстового содержимого (однако, возможно, имеет дочерние элементы, поэтому смешивайте и сопоставляйте эти случаи по мере необходимости)
Комментарии:
1. Очень удобно, это позволяет избежать выполнения проверки exists.
Ответ №3:
вы можете проверить, есть ли у узла данные перед обновлением, такие как:
IF EXISTS(
SELECT null
FROM filemetaDB
WHERE cast(filemeta.query('if (/filemeta/description[1]) then "T" else ""') as varchar) = 'T')
BEGIN
UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/description/text())[1] with "notworking!"');
END
Ответ №4:
Я думаю, что этот метод не будет работать для пустых узлов.
Вы также могли бы проверить это дополнение: ссылка