Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Добавить элемент в XML  [new]
iluxa1810
Member

Откуда:
Сообщений: 148
Есть таблица, которая имеет поле с типом XML.
XML имеет следующий вид:
<root>
    <Personals>
    <Person> 
        <FIO>?.?. Герасимов</FIO>
        <Date>?1.10.198?</Date>
        <City>Москва</City>
    <Person>
    <Person> 
        <FIO>В.В. Николаев</FIO>
        <Date>01.10.1!8!</Date>
        <City>Краснодар</City>
    <Person>
    <Person> 
        <FIO>Г.В. Петров</FIO>
        <Date>06.09.1988</Date>
        <City>Москва</City>
    <Person>
    </Personals>
    <other>Какие-то другие поля. Не имеет значения</other>
</root>

Необходимо добавить элемент <Pr>1</Pr> в те Person, где или FIO или Date содержит в себе ? или !(Могут находится в любых частях предложения).
Если Person не удовлетворяет условиям, то добавить <Pr>1</Pr>.
Подскажите, как это сделать?
19 мар 15, 23:45    [17407598]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
iluxa1810, как то так?

declare @testxml as xml = '<root>
    <Personals>
    <Person> 
        <FIO>?.?. Герасимов</FIO>
        <Date>?1.10.198?</Date>
        <City>Москва</City>
    </Person>
    <Person> 
        <FIO>В.В. Николаев</FIO>
        <Date>01.10.1!8!</Date>
        <City>Краснодар</City>
    </Person>
    <Person> 
        <FIO>Г.В. Петров</FIO>
        <Date>06.09.1988</Date>
        <City>Москва</City>
    </Person>
    </Personals>
    <other>Какие-то другие поля. Не имеет значения</other>
</root>';


while @testxml.exist('/root/Personals/Person[not(Pr) and (contains((FIO/text())[1], "?") or contains((Date/text())[1], "!"))]') = 1

	set @testxml.modify(' insert <Pr>1</Pr>
as first     
into (/root/Personals/Person[not(Pr) and (contains((FIO/text())[1], "?") or contains((Date/text())[1], "!"))])[1]  
')       

select @testxml
20 мар 15, 10:22    [17408473]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
iluxa1810
Member

Откуда:
Сообщений: 148
Minamoto
iluxa1810, как то так?

declare @testxml as xml = '<root>
    <Personals>
    <Person> 
        <FIO>?.?. Герасимов</FIO>
        <Date>?1.10.198?</Date>
        <City>Москва</City>
    </Person>
    <Person> 
        <FIO>В.В. Николаев</FIO>
        <Date>01.10.1!8!</Date>
        <City>Краснодар</City>
    </Person>
    <Person> 
        <FIO>Г.В. Петров</FIO>
        <Date>06.09.1988</Date>
        <City>Москва</City>
    </Person>
    </Personals>
    <other>Какие-то другие поля. Не имеет значения</other>
</root>';


while @testxml.exist('/root/Personals/Person[not(Pr) and (contains((FIO/text())[1], "?") or contains((Date/text())[1], "!"))]') = 1

	set @testxml.modify(' insert <Pr>1</Pr>
as first     
into (/root/Personals/Person[not(Pr) and (contains((FIO/text())[1], "?") or contains((Date/text())[1], "!"))])[1]  
')       

select @testxml

Да, похоже на правду.
Но я немного ошибся в первом посте, и нужно добавлять pr=1(Когда в одном из полей есть ? и !) в одном случае, а pr=2 в другом случае.(Когда не в одном поле их нет.)
Можно ли это сделать?

Конечно, напрашивается еще один modify с другими условиями, но можно ли сделать это как-то иначе?
21 мар 15, 00:05    [17412626]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
iluxa1810
Member

Откуда:
Сообщений: 148
Еще вопрос, а если бы у меня был такой XML:
<root>
    <Personals>
    <Person> 
       <Pr/>
        <FIO>?.?. Герасимов</FIO>
        <Date>?1.10.198?</Date>
        <City>Москва</City>
    <Person>
    <Person> 
        <Pr/>
        <FIO>В.В. Николаев</FIO>
        <Date>01.10.1!8!</Date>
        <City>Краснодар</City>
    <Person>
    <Person> 
      <Pr/> 
       <FIO>Г.В. Петров</FIO>
        <Date>06.09.1988</Date>
        <City>Москва</City>
    <Person>
    </Personals>
    <other>Какие-то другие поля. Не имеет значения</other>
</root>

То как бы в таком случае осуществялось обновление Pr?
21 мар 15, 14:39    [17413723]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
iluxa1810
Member

Откуда:
Сообщений: 148
Плз, помогите.
22 мар 15, 12:33    [17416195]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
Klemzig
Guest
iluxa1810,

Если только через FLWOR:

+
declare @t table (
	Id int identity(1,1) primary key,
	x xml not null
);

insert into @t (x)
select N'<root>
  <Personals>
    <Person>
			<Pr />
      <FIO>?.?. Герасимов</FIO>
      <Date>?1.10.198?</Date>
      <City>Москва</City>
    </Person>
    <Person>
			<Pr />
      <FIO>В.В. Николаев</FIO>
      <Date>01.10.1!8!</Date>
      <City>Краснодар</City>
    </Person>
    <Person>
			<Pr />
      <FIO>Г.В. Петров</FIO>
      <Date>06.09.1988</Date>
      <City>Москва</City>
    </Person>
  </Personals>
  <other>Какие-то другие поля. Не имеет значения</other>
</root>';

select * from @t;

-- Insert new one
update t set x.modify('insert
<Personals> {
for $per in /root/Personals/Person
return
<Person>
	{
	if (
		contains(($per/FIO/text())[1], ''?'')
		or contains(($per/FIO/text())[1], ''!'')
		or contains(($per/Date/text())[1], ''?'')
		or contains(($per/Date/text())[1], ''!'')
	) then
	<Pr>1</Pr>
	else
	<Pr>2</Pr>
	}
	{$per/FIO}
	{$per/Date}
	{$per/City}
</Person> }
</Personals>
as first into /root[1]
')
from @t t;

-- Delete the old one
update @t set x.modify('delete /root[1]/Personals[2]')

select * from @t;
Но даже в этом случае сиквел не дает сделать все в один проход, в результате приходится менять UPDATE на INSERT+DELETE.

P.S.: И да, кстати: применимость данного решения будет сильно зависеть от результата вашего print @@version, т.к. реализация спецификаций W3C в сиквеле сильно зависит от версии оного. Я это писал и тестил на 2014, остальных версий под рукой нет.

PPS: А еще у вас XML хронически невалидный.
23 мар 15, 05:15    [17417508]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Добавить элемент в XML  [new]
еще вопрос
Guest
Всем доброго дня.

нужно вставить один тэг в другой родительский, а если нет родительского, то его тоже создать
в коде выгляди так:

declare @temp table (fl xml)

insert into @temp (fl)
values ('<yy><tt ID="1" /></yy>'), ('<zz>1</zz>'), (null)

update @temp set
	fl.modify('insert <new Id="newID">new</new> as last into (/yy)[1]')
where fl.exist('/yy') = 1

update @temp set
	fl.modify('insert <yy><new Id="newID">new</new></yy> as last into (/)[1]')
where fl.exist('/yy') = 0

update @temp set 
	fl = '<yy><new Id="newID">new</new></yy>'
where fl is null 

т.е.
было				стало
<yy><tt ID="1" /></yy> <yy><tt ID="1" /><new Id="newID">new</new></yy>
<zz>1</zz> <zz>1</zz><yy><new Id="newID">new</new></yy>
NULL <yy><new Id="newID">new</new></yy>

как это можно сделать одним запросом, в крайнем случае с двумя запросами (отдельно для NULL и не NULL)?
не могу сообразить в конструкции вида
update @temp set
	fl.modify('
	insert
	if ( count(/yy) = 0 )
	then <yy><new Id="newID">new</new></yy>
	else (<yy><new Id="newID">new</new></yy>)
	as last into (/)[1]
	')
where fl is not null

как выбрать родительский элемент если он уже имеется? или такое невозможно?
13 дек 16, 13:30    [19997040]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
еще вопрос
Guest
сделал такой вариант

declare @temp table (fl xml)

declare @NewXML xml = '<Master_1><NEW_Slave Id="NEW_Slave_ID">new</NEW_Slave></Master_1>'

insert into @temp (fl)
values ('<Master_1><Slave_1 ID="1" /></Master_1>'), ('<Master_222>2</Master_222>'), (null)

select
	[current] = fl,
	[new] = @NewXML,
	[merge] = cast((select case when fl is null then cast('' as xml) else fl end, @NewXML for xml path ('')) as xml)
from @temp t

результат получился

<Master_1><Slave_1 ID="1" /></Master_1><Master_1><NEW_Slave Id="NEW_Slave_ID">new</NEW_Slave></Master_1>
<Master_222>2</Master_222><Master_1><NEW_Slave Id="NEW_Slave_ID">new</NEW_Slave></Master_1>
<Master_1><NEW_Slave Id="NEW_Slave_ID">new</NEW_Slave></Master_1>

вот втором и третьем случае все нормально
а в первом не произошло слияния, получили две ветки с <Master_1>
подскажите пожалуйста как поместить в уже существующий контейнер. а не создавать новый?
как вариант можно для этого случая сделать:
declare @NewXML_1 xml = '<NEW_Slave Id="NEW_Slave_ID">new</NEW_Slave>'
но вопрос остается как значение @NewXML_1 поместить в <Master_1></Master_1>
14 дек 16, 11:40    [20001468]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
@xml.modify( ... replace ... )
14 дек 16, 16:12    [20003322]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
еще вопрос
Guest
Руслан Дамирович,
задача поменялась, нужно не обновлять таблицу, а селектить из нее. Как вариант можно сначала обновить, а потом из нее сделать селект. Но получается накладно.
16 дек 16, 16:44    [20013153]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
еще вопрос
Guest
всем привет

делаю следующее, в общем то устраивает, но все же как сделать чистым xml-ным методом без
cast(cast(field_xml as nvarchar(max)) + (...) as xml)
declare @t table (field_xml xml, field_int int, field_nvarchar nvarchar(100))

insert into @t (field_xml, field_int, field_nvarchar)
select '<Type>Type_1</Type><Params><Param Id="Id_1">22</Param><Param Id="Code_1">33</Param></Params>', 10, 'test'
union all select null, 20, 'test20'

select 
	cast (
		isnull(cast(field_xml as nvarchar(max)), '')
		+  (
			select
				[Param/@Id] = 'field_int',
				[Param] = inner_t.field_int, N'',
				[Param/@Id] = 'field_nvarchar',
				[Param] = inner_t.field_nvarchar, N''
			from (
					select t.field_int, t.field_nvarchar
				) as inner_t
			for xml path('SyncData')
		)
	as xml )
from @t t
8 фев 17, 17:14    [20194190]     Ответить | Цитировать Сообщить модератору
 Re: Добавить элемент в XML  [new]
Кесарь
Member

Откуда:
Сообщений: 453
Коллеги, а чем не устраивает стандартная функциональность? Это ж не json, поддержка которого только что появилась, sql server с xml уже много лет работать умеет.

https://social.technet.microsoft.com/wiki/ru-ru/contents/articles/11778.xml-sql-server-1.aspx
8 фев 17, 17:31    [20194249]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить