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

Откуда:
Сообщений: 7
Друзья, помогите.

Есть xml файл такого типа
<root>
<pok id="1" val1="3" val2="7"/>
<pok id="2" val3="5/>
<pok id="3" val2="6"/>
<pok id="4" val4="7">
<pok id="5" val1="13" val2="17"/>
<pok id="6" val1="15/>
</root>
Названия атрибутов (кроме атрибута id) могут быть произвольными. Число их также не известно.

И есть таблица
id name value
--- ---- ------
1 val1 1111
4 val4 2222
5 val2 4444
6 val1 6666

Взяв value таблицы, надо изменить значения у показателей с соответствующим id и именем атрибута. Остальные же значения оставить без изменения.
23 май 11, 23:00    [10697256]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Можно даже поспорить, что сначала сами же выбрали работать черех xml, а теперь мудахайтесь с ним. Не?
Или начайнег сферъху так над вами издевается.

Может стоит поменять систему пока не поздно?

Вот наводящий скрипт.
DECLARE	@XML = '<root>
<pok id="1" val1="3" val2="7"/>
<pok id="2" val3="5/>
<pok id="3" val2="6"/>
<pok id="4" val4="7">
<pok id="5" val1="13" val2="17"/>
<pok id="6" val1="15/>
</root>'

SELECT	 N.X.value('@id'		,'Int')
	,A.X.value('local-name(.)'	,'VarChar(32)')
	,A.X.value('data(.)'		,'VarChar(512)')
FROM	           @XML.nodes('/root/*')	N(X)
	CROSS APPLY N.X.nodes('@*')		A(X)
--	CROSS APPLY N.X.nodes('@*[local-name(.) <> "id"]') A(X)
-- WHERE A.X.value('local-name(.)'	,'VarChar(32)') != 'id'
Может где-то опечатки.
23 май 11, 23:26    [10697336]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
iokulinar
Member

Откуда:
Сообщений: 7
Mnior,

Работа через xml действительно не мой выбор :)
В приведенном скрипте в таблицу запихиваем распарсенный xml, но самое сложное как раз не в этом. Трудно именно заменить значения. Или вы хотите потом "пересобрать" xml заново через for xml auto?

Вопрос пока актуален :(
24 май 11, 11:58    [10699081]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
iokulinar
Member

Откуда:
Сообщений: 7
Коллеги, а написал одно из возможных решений. Корявенькое, но надеюсь поможем всем, кто активно работает c xml в sql

declare @tab2 table (id decimal(20,0),name varchar(255), value varchar(255))
insert into @tab2 values ('3','val1','123')
insert into @tab2 values ('3','val2','134')
insert into @tab2 values ('4','val1','456')
insert into @tab2 values ('5','val3','789')
insert into @tab2 values ('6','val4','234')
insert into @tab2 values ('6','val7','567')
	
declare @a as varchar(255) = 'val1'
declare @x as xml
set @x='
<root>
	<pok id="1">значение 1</pok>
	<pok id="2" val1="значение 2"/>
	<pok id="3" val2="значение 3"/>
	<pok id="4" val1="значение 4"/>
	<pok id="5" val3="значение 5"/>
	<pok id="6" val4="значение 6" val7="111"/>
	<tag number="1" pok="188" val=""/>
</root>
'
if OBJECT_ID('tempdb.dbo.#tab2') is not null drop table #tab2
create table #tab2 (xml xml)
insert into #tab2 values (@x)

declare 
	@id as int
	,@name as varchar(255)
	,@value as varchar(255)
	
declare updatexmlvalue cursor for
select id,name,value
from @tab2
open updatexmlvalue
fetch next from updatexmlvalue into @id, @name, @value
WHILE @@FETCH_STATUS = 0
BEGIN	

	exec ('declare @x as xml
	set @x=(select xml from #tab2) 
	set @x.modify(''replace value of (/root/pok[@id='+@id+']/@*[local-name(.) = "'+@name+'"])[1]
			with "'+@value+'"'')
	delete 	#tab2	
	insert into #tab2 values (@x)')
	
	fetch next from updatexmlvalue into @id, @name, @value
END
close updatexmlvalue deallocate updatexmlvalue	
	
select * from #tab2	
24 май 11, 13:27    [10699745]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
iokulinar
Или вы хотите потом "пересобрать" xml заново?
Согласен, это уже задрало.

DECLARE	@Table TABLE (
	 id	Int		NOT NULL
	,name	VarChar(32)	NOT NULL
	,value	VarChar(512)	    NULL
	,PRIMARY KEY (
		 id
		,name
	)
)INSERT	@Table VALUES
 (1,'val1','1111')
,(4,'val4','2222')
,(5,'val2','4444')
,(6,'val1','6666')
----------------------------------------
DECLARE	@XML XML = '
<root>
 <pok id="1" val1="3" val2="7"/>
 <pok id="2" val3="5"/>
 <pok id="3" val2="6"/>
 <pok id="4" val4="7"/>
 <pok id="5" val1="13" val2="17"/>
 <pok id="6" val1="15"/>
</root>'
Вариант 1:
DECLARE	@Root TABLE (X XML NOT NULL)
INSERT	@Root
SELECT	N.X.query('.')
FROM	@XML.nodes('/root/*')N(X)

UPDATE	R
SET	X.modify('replace value of (*/@*[local-name(.) = sql:column("T.name")])[1] with sql:column("T.value")')
FROM	           @Root					R
	CROSS APPLY R.X.nodes('*[1]/@*[local-name(.) != "id"]')	A(X)
	      JOIN @Table					T ON T.id   = R.X.value('*[1]/@id'	,'Int')
								 AND T.name = A.X.value('local-name(.)'	,'VarChar(32)')
SELECT	X [*]
FROM	@Root
FOR XML Path(''),Root('root'),Type
Вариант 2:
DECLARE	@Temp TABLE (X XML NOT NULL)
INSERT	@Temp VALUES (@XML)

UPDATE	R
SET	X.modify('replace value of (/root/*[@id = sql:column("T.id")]/@*[local-name(.) = sql:column("T.name")])[1] with sql:column("T.value")')
FROM	            @Temp					R
	CROSS APPLY R.X.nodes('/root/*')			N(X)
	CROSS APPLY N.X.nodes('@*[local-name(.) != "id"]')	A(X)
	      JOIN @Table					T ON T.id   = N.X.value('@id'		,'Int')
								 AND T.name = A.X.value('local-name(.)'	,'VarChar(32)')
SELECT X FROM @Temp
24 май 11, 17:14    [10701637]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
iokulinar
но надеюсь поможем всем, кто активно работает c xml в sql
Надеюсь все это проигнорируют. Курсоры must die!
24 май 11, 17:16    [10701650]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
2 Модераторы

а давате поселим ето в FAQ, ровно как и примеры с СТЕ от iap ?
24 май 11, 17:20    [10701671]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Добавление топика в FAQ
24 май 11, 18:07    [10702048]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
Mnior
Добавление топика в FAQ


ну как минимум,ето должен делать автор... имхо,а то некрасиво получится
24 май 11, 18:08    [10702052]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381

> Надеюсь все это проигнорируют. Курсоры must die!

так, эта... не то, чтоб я против был, но:

"Вариант 1" не все обновит для

(1,'val1','1111')
,(1,'val2','7777')

а "Вариант 2" вообще же обновляет только 1 значение.

?

нет, оно можно и без курсора как-нибудь, конечно, но не вот так вот уж просто.

Posted via ActualForum NNTP Server 1.4

24 май 11, 18:11    [10702066]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Maxx
ну как минимум,ето должен делать автор... имхо,а то некрасиво получится
Опа, я уже что-то должен?

daw, вы правы, а главное в голове отчётливо крутится, а ... <харе отмазываться>
24 май 11, 18:45    [10702303]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
Mnior,

причем тут должен..я вообще такого не говорил
сорри если зацепил
24 май 11, 18:46    [10702308]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Maxx
причем тут должен..я вообще такого не говорил
сорри если зацепил
Да нет всё правильно. Лень и время, блин.
Меня больше "2 Модераторы" сбило.
24 май 11, 19:05    [10702407]     Ответить | Цитировать Сообщить модератору
 Re: Замена значений атрибутов в xml  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
+ вот упёртый, ну
DECLARE	@Root TABLE (X XML NOT NULL)
INSERT	@Root SELECT N.X.query('.') FROM @XML.nodes('/root/*')N(X)
UPDATE R SET X.modify('insert sql:column("I.X") after *[1]')
FROM	@Root R CROSS APPLY(SELECT(
		SELECT	 T.name		AS [@name]
			,T.value	AS [@value]
		FROM	R.X.nodes('*[1]/@*')	A(X)
			JOIN @Table		T ON T.id   = R.X.value('*[1]/@id'	,'Int')
						 AND T.name = A.X.value('local-name(.)'	,'VarChar(32)')
		FOR XML Path('replace'),Type))	I(X)
WHILE (@@RowCount > 0) BEGIN
	UPDATE @Root SET X.modify('
		replace value of /*[1]/@*[local-name(.) = /*[2]/@name][1]
		with /*[2]/@value')			WHERE X.exist('*[2]') = 1
	UPDATE @Root SET X.modify('delete /*[2]')	WHERE X.exist('*[2]') = 1
END
SET @XML = (SELECT X [*] FROM @Root FOR XML Path(''),Root('root'),Type)
SELECT @XML
Ну конечно же на 2008м.
Да, с курсором или динамикой по типам name предпочтительнее. Естественно не так как здесь: 10699745

Задача изврат. XML на скуле изврат.
25 май 11, 11:20    [10704890]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить