Управление столбцом xml на сервере sql с помощью Xquery - PullRequest
0 голосов
/ 15 октября 2010

Я храню файл xml в типе данных xml в таблице SQL Server. Теперь я хочу получить некоторые фрагменты (используя xquery), а затем обновить фрагменты измененными фрагментами (используя xquery). Мне нужны предложения.

У меня есть код для удаления узла, как показано ниже, но при удалении мне нужно вставить измененный узел в то же место. Как это можно сделать?

--SET @doc.modify('delete (/DATA/SDACTS)')

Это работает, если я хочу удалить узел, но как насчет вставки измененного узла в то же место

Далее я хочу удалить узлы, значения которых будут переданы в виде строки запроса, поэтому мне нужно создать строку

как показано ниже

DECLARE @x XML 

SET @x = '
<DATA>
  <SDACTS>
    <SDACT TYPE="Economy" COLOUR="0xff0000" />
    <SDACT TYPE="Environment" COLOUR="0x00ff00" />
    <SDACT TYPE="People" COLOUR="0x0000ff" />
    <SDACT TYPE="Society" COLOUR="0xff00ff" />
  </SDACTS>
<LOCATIONS>
    <CONTINENT TITLE="South America">
      <COUNTRY TITLE="Chile">
        <HEADOFFICE>Santiago</HEADOFFICE>
        <ADDRESS>
          &lt;p&gt;Pedro de Valdivia 291&lt;/p&gt;&lt;p&gt;Providencia&lt;/p&gt;&lt;p&gt;Santiago&lt;/p&gt;
        </ADDRESS>
        <LATITUDE>-33.426127</LATITUDE>
        <LONGITUDE>-70.611469</LONGITUDE>
        <BUSINESSUNITS>Copper</BUSINESSUNITS>        
        <EMPLOYEES />
        <NUMBEROFBUSINESS>1</NUMBEROFBUSINESS>
      </COUNTRY>
      <COUNTRY TITLE="Brazil">
        <HEADOFFICE>Brazil</HEADOFFICE>
        <ADDRESS>
          &lt;p&gt;Pedro de Valdivia 291&lt;/p&gt;&lt;p&gt;Providencia&lt;/p&gt;&lt;p&gt;Santiago&lt;/p&gt;
        </ADDRESS>
        <LATITUDE>-38.426127</LATITUDE>
        <LONGITUDE>-60.611469</LONGITUDE>
        <BUSINESSUNITS>Zinc</BUSINESSUNITS>        
        <EMPLOYEES />
        <NUMBEROFBUSINESS>2</NUMBEROFBUSINESS>
      </COUNTRY>
    </CONTINENT>
</LOCATIONS>
</DATA>

Я должен удалить страну Бразилию, которая находится на континенте Южная Америка, поэтому я должен сохранить их в качестве параметров, которые должны быть динамичными, так как может прийти другая страна и континент.

declare @country varchar(50)
declare @continent  varchar(50)
set @country = 'Brazil'
set @continent = 'South America'

declare @final varchar(100)
set @final = '//CONTINENT[@TITLE="' + @continent + '"]/COUNTRY[@TITLE="' + @country + '"]'
select @final
--SELECT @doc.query('sql:variable("@final")') 'XmlDesc'  This works for select statement but not for delete
SET @doc.modify('delete (sql:variable("@final"))')   This does not work and gives error.
 SELECT @doc

Мое требование:

В основном я делаю инструмент редактирования xml в .NET, и дерево jQuery зависает при загрузке огромных файлов xml, поэтому я сохраняю огромный файл xml в таблице и вызываю сегменты (дочерние узлы), а затем загружаю эти сегменты в дерево jquery и Пользователь изменяет эти узлы. Я беру измененные сегменты в базу данных, а затем хочу обновить с измененным.

1 Ответ

1 голос
/ 15 октября 2010

Редактировать 2 : похоже, что SLQ-сервер не является полностью обработанным XQuery-процессором с жалобами ...

Итак, более "статичный" XQuery (которыйхорошо, если схема хорошо известна):

declare variable $continent external;
declare variable $country external;
declare variable $xml as item() external;
element DATA {
   /DATA/@*,
   /DATA/*[not(self::LOCATIONS)],
   element LOCATIONS {
      /DATA/LOCATIONS/@*,
      for $cont in /DATA/LOCATIONS/CONTINENT
      return element CONTINENT {
                $cont/@*,
                for $count in $cont/COUNTRY
                return if ($cont/@TITLE=$continent and
                           $count/@TITLE=$country)
                       then $xml
                       else $count
             }
   }
}

С этими параметрами (с SQL-сервером вы также можете использовать sql:variable() функцию расширения):

continent="'South America'"
country="'Brazil'"
xml="<COUNTRY TITLE='Brazil'><UPDATE/></COUNTRY>"

Вывод:

<DATA>
    <SDACTS>
        <SDACT TYPE="Economy" COLOUR="0xff0000"/>
        <SDACT TYPE="Environment" COLOUR="0x00ff00"/>
        <SDACT TYPE="People" COLOUR="0x0000ff"/>
        <SDACT TYPE="Society" COLOUR="0xff00ff"/>
    </SDACTS>
    <LOCATIONS>
        <CONTINENT TITLE="South America">
            <COUNTRY TITLE="Chile">
                <HEADOFFICE>Santiago</HEADOFFICE>
                <ADDRESS>
          &lt;p&gt;Pedro de Valdivia 291&lt;/p&gt;&lt;p&gt;Providencia&lt;/p&gt;&lt;p&gt;Santiago&lt;/p&gt;
                </ADDRESS>
                <LATITUDE>-33.426127</LATITUDE>
                <LONGITUDE>-70.611469</LONGITUDE>
                <BUSINESSUNITS>Copper</BUSINESSUNITS>
                <EMPLOYEES/>
                <NUMBEROFBUSINESS>1</NUMBEROFBUSINESS>
            </COUNTRY>
            <COUNTRY TITLE="Brazil">
                <UPDATE/>
            </COUNTRY>
        </CONTINENT>
    </LOCATIONS>
</DATA>

РЕДАКТИРОВАТЬ 3 : Я думаю, что правильный синтаксис для вашего запроса в комментариях:

declare @continent varchar(100) 
declare @country varchar(100) 
declare @xml xml 
declare @count int 
declare @doc xml 
set @continent='South America' 
set @country='Brazil' 
set @xml='<COUNTRY TITLE="Brazil"><UPDATE/></COUNTRY>' 
set @count = 1 
select @doc = xmldesc from varunxmlanglo where idlanguage =1 and xmltype ='D' 
select @doc.query('
element DATA {
   /DATA/@*,
   /DATA/*[not(self::LOCATIONS)],
   element LOCATIONS {
      /DATA/LOCATIONS/@*,
      for $continent in /DATA/LOCATIONS/CONTINENT
      return element CONTINENT {
                $continent/@*,
                for $country in $continent/COUNTRY
                return if ($continent/@TITLE=sql:variable("@continent") and                                                       $country/@TITLE=sql:variable("@country"))
                       then sql:variable("@xml")
                       else $country
             }
   }
}
')

Примечание : в переменной XQueryссылка имеет префикс $.

...