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

Откуда:
Сообщений: 53
Добрый день!
Прошу помощи.
T-SQL, SQL Server 2005.

Есть таблица, одно поле содержит xml контейнер:
<amountDetail>
  <accumPeriod datestart="25.07.2017" datefinish="31.07.2017" />
  <amountList>
    <amountItem perioddatestart="25.07.2017" >20.00</amountItem>
    <amountItem perioddatestart="31.07.2017" >20.00</amountItem>
  </amountList>
</amountDetail>


Апдейт атрибута perioddatestart делаю так:
Set @container.modify('replace value of (/amountDetail/amountList/amountItem/@perioddatestart)[1] with concat(substring((/amountDetail/amountList/amountItem/@perioddatestart)[1],7,4),"-",substring((/amountDetail/amountList/amountItem/@perioddatestart)[1],4,2),"-",substring((/amountDetail/amountList/amountItem/@perioddatestart)[1],1,2))')


Но надо делать апдейт по всем одноранговым нодам, то есть по всем amountItem. Как ни пытаюсь, не получается обновлять, если не синглетон.

Есть идеи?

Спасибо!
29 авг 17, 14:45    [20756291]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
LSV
Member [заблокирован]

Откуда: Киев
Сообщений: 30817
офф: Был тут один умник, кот. агитировал активно использовать XML для запросов.
Вот пусть он и отвечает. :)

зы: И чем людям обычные таблицы и поля не подошли ? В чем прикол использования таких извращений ?
29 авг 17, 14:55    [20756317]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
Minamoto
Member

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

declare @amountList xml,
         @container xml = '<amountDetail>
  <accumPeriod datestart="25.07.2017" datefinish="31.07.2017" />
  <amountList>
    <amountItem perioddatestart="25.07.2017" >20.00</amountItem>
    <amountItem perioddatestart="31.07.2017" >20.00</amountItem>
  </amountList>
</amountDetail>'

select @amountList = (
                        select  convert(varchar(10), convert(date, c.ai.value('@perioddatestart[1]', 'varchar(10)'), 104), 120) as '@perioddatestart'
                            ,   c.ai.value('text()[1]', 'decimal(10, 2)')
                        from    @container.nodes('/amountDetail/amountList/amountItem') as c(ai)
                        for xml path ('amountItem'), root ('amountList'));

set @container.modify('delete (/amountDetail/amountList)[1]');

set @container.modify('insert sql:variable("@amountList") into (/amountDetail)[1]');

select @container;
29 авг 17, 15:23    [20756442]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
Browny
Member

Откуда:
Сообщений: 53
Minamoto,
видимо, синтаксис рассчитан на SQL Server > 2005. Поправил много мелких ошибок, в итоге всё упёрлось в
XQuery [modify()]: Only non-document nodes can be inserted. Found "xs:string ?".
29 авг 17, 15:31    [20756472]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
Browny
Member

Откуда:
Сообщений: 53
Minamoto, но, в целом, направление понятно - выбрать целиком секцию, переформировать, заменить.
29 авг 17, 15:33    [20756482]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
invm
Member

Откуда: Москва
Сообщений: 9127
use tempdb;
go

create function dbo.fnUpdateXML
(
 @x xml
)
returns xml
as
begin
 declare @i int, @c int;

 select
  @i = 1,
  @c = @x.value('count(//amountItem)', 'int');

 while @i <= @c
  begin
   set @x.modify('replace value of ((//amountItem[sql:variable("@i")])[1]/@perioddatestart) with concat(substring((//amountItem[sql:variable("@i")])[1]/@perioddatestart,7,4),"-",substring((//amountItem[sql:variable("@i")])[1]/@perioddatestart,4,2),"-",substring((//amountItem[sql:variable("@i")])[1]/@perioddatestart,1,2))');
   set @i = @i + 1;
  end;

 return @x;
end;
go

declare @x xml = '<amountDetail>
  <accumPeriod datestart="25.07.2017" datefinish="31.07.2017" />
  <amountList>
    <amountItem perioddatestart="25.07.2017" >20.00</amountItem>
    <amountItem perioddatestart="31.07.2017" >20.00</amountItem>
  </amountList>
</amountDetail>'

declare @t table (x xml);
insert into @t
 select @x union all select @x union all select @x;

update @t set x = dbo.fnUpdateXML(x);

select @x, x from @t;
go

drop function dbo.fnUpdateXML;
go
29 авг 17, 15:38    [20756497]     Ответить | Цитировать Сообщить модератору
 Re: Массовый update одноуровневых нодов xml на XQuery  [new]
Browny
Member

Откуда:
Сообщений: 53
invm, спасибо, хороший вариант! Думаю, цикл можно даже в XQuery разместить.
29 авг 17, 15:41    [20756507]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить