openxml где пункт для обновления sql

это мой xml

<root>
<children>
 <child id = "1">
  <description>This is child 1</description>
 </child>
 <child id = "2">
    <description>This is child 2</description>
 </child>
 <child id = "3">
    <description>This is child 3</description>
 </child>
</children>
</root>

Я пытаюсь обновить таблицу с именем Child, в которой есть столбцы «ID» и «Описание». В таблице уже есть значения столбца ID, но описание пустое. Мне нужно обновить это описание по идентификатору из приведенного выше XML-файла.

Я попытался выполнить OPENXML со значением флага 2 (ориентированным на элементы) и смог получить все описания. Но я не знаю, как получить описания на основе значений идентификатора, используя предложение where в OPENXML.

Я использую базу данных SQL Server 2008.
(Будет ли OPENXML работать и с SQL Server 2005?)

Это то, что я пытался сделать:

DECLARE @idoc int DECLARE @doc xml

select @doc= c from openrowset(bulk 'C:\Test.xml',single_blob) as temp(c)
exec sp_xml_preparedocument @idoc output, @doc 

SELECT * FROM OPENXML (@idoc, '/root/children/child', 2)
  WITH (summary  varchar(1000)) descr 
EXEC sp_xml_removedocument @idoc

Заранее спасибо Ник

p.s. Структуру xml изменить нельзя. Мне нужно обойти это ограничение.


person Nishant    schedule 23.02.2011    source источник
comment
Ваш xml недействителен. Атрибуты должны быть <child id = "1"> с двойными кавычками. Это опечатка или xml действительно выглядит так?   -  person Mikael Eriksson    schedule 23.02.2011
comment
я внес изменения. это была опечатка. Извините   -  person Nishant    schedule 23.02.2011


Ответы (1)


Предполагая, что вы используете SQL Server 2005 или выше, и ваш XML хранится в переменной с именем @input, вы можете попробовать это:

declare @input XML 

set @input = '<root>
<children>
 <child id="1">
  <description>This is child 1</description>
 </child>
 <child id="2">
    <description>This is child 2</description>
 </child>
 <child id="3">
    <description>This is child 3</description>
 </child>
</children>
</root>'

;with GrabXML AS
(
    select
        child.value('@id', 'int') as 'ID',
        child.value('(description)[1]', 'varchar(50)') as 'Description'
    from
        @input.nodes('/root/children/child') as n(Child)
)
update dbo.Child
set description = g.Description
from GrabXML g
where dbo.Child.ID = g.ID

Общее табличное выражение GrabXML (CTE) анализирует и объединяет XML в строки и столбцы, а следующая инструкция UPDATE использует эти строки/столбцы для обновления существующей таблицы.

Обновление: есть две возможные проблемы, если ваши строки длиннее, чем вы ожидаете:

во-первых, вам может понадобиться увеличить длину преобразования из XML:

select
   child.value('@id', 'int') as 'ID',
   child.value('(description)[1]', 'varchar(999)') as 'Description'

а во-вторых, вам нужно проверить, какой длины ваш столбец в таблице dbo.Child, и обрезать длину строки, извлеченной из XML, чтобы она не превышала длину столбца базы данных:

update dbo.Child
set description = SUBSTRING(g.Description, 1, 575)

Здесь вам нужно извлечь не более столько символов из строки g.Description, сколько позволяет столбец dbo.Child.description вашей базы данных.

person marc_s    schedule 23.02.2011
comment
спасибо марк. но я загружаю xml из файла. Отредактировал мой пост. (Это то, что я пытаюсь сделать) - person Nishant; 23.02.2011
comment
@Nick - используйте код Марка, начиная со строки ;with GrabXML, предварительно добавив эту часть кода DECLARE @input xml select @input= c from openrowset(bulk 'C:\Test.xml',single_blob) as temp(c) - person RichardTheKiwi; 23.02.2011
comment
Приведенное выше решение Марка сработало. Но иногда происходит сбой со следующей ошибкой: Msg 8152, уровень 16, состояние 14, строка 2 Строка или двоичные данные будут усечены. Заявление было прекращено. Вероятно, это связано с огромным объемом данных, которые не может принять переменная @doc типа XML. Что может быть возможным обходным путем для этого? - person Nishant; 25.02.2011
comment
@nick: какой-то столбец в вашей целевой таблице явно слишком короткий для данных, которые вы импортируете... - person marc_s; 25.02.2011