使用 Xquery 操作 sql server 中的 xml 列

发布于 2024-09-27 06:53:13 字数 2605 浏览 6 评论 0原文

我将 xml 文件存储在 SQL Server 表中的 xml 数据类型中。现在我想获取一些片段(使用 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

我的要求:

基本上我正在.NET中制作一个xml编辑工具,并且加载巨大的xml文件时jQuery树会挂起,因此我将巨大的xml文件存储在表中并调用段(子节点),然后将这些段加载到jquery树中并用户修改这些节点。我将修改后的段存入数据库,然后想用修改后的段进行更新。

I am storing an xml file in the xml datatype in table of SQL Server. Now I want to fetch some fragments (using xquery) and then update the fragments with the modified fragments (using xquery). I need some suggestions.

I have the code to delete a node and it is as below but while deleting I need to insert the modified node at the same place. How can this be done?

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

This works if I want to delete a node but what about inserting the modified node at same location

Next I want to delete the nodes whose values will be passed as querystring so I have to build up the string

like below

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>
          <p>Pedro de Valdivia 291</p><p>Providencia</p><p>Santiago</p>
        </ADDRESS>
        <LATITUDE>-33.426127</LATITUDE>
        <LONGITUDE>-70.611469</LONGITUDE>
        <BUSINESSUNITS>Copper</BUSINESSUNITS>        
        <EMPLOYEES />
        <NUMBEROFBUSINESS>1</NUMBEROFBUSINESS>
      </COUNTRY>
      <COUNTRY TITLE="Brazil">
        <HEADOFFICE>Brazil</HEADOFFICE>
        <ADDRESS>
          <p>Pedro de Valdivia 291</p><p>Providencia</p><p>Santiago</p>
        </ADDRESS>
        <LATITUDE>-38.426127</LATITUDE>
        <LONGITUDE>-60.611469</LONGITUDE>
        <BUSINESSUNITS>Zinc</BUSINESSUNITS>        
        <EMPLOYEES />
        <NUMBEROFBUSINESS>2</NUMBEROFBUSINESS>
      </COUNTRY>
    </CONTINENT>
</LOCATIONS>
</DATA>

I have to delete the country brazil which lies in the continent South America so I have to keep these as parameters which has to be dynamic as other country and continent can come.

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

My requirement:

Basically I am making a xml editing tool in .NET and jQuery tree hangs when loading huge xml files so I am storing the huge xml file in table and calling the segments (child nodes) and then loading those segments in jquery tree and user modifies those node. I take the modified segments to the database and then want to update with the modified one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你是年少的欢喜 2024-10-04 06:53:13

编辑2:看起来SLQ-Server不是一个完全兼容的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-Server,您还可以使用 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>
          <p>Pedro de Valdivia 291</p><p>Providencia</p><p>Santiago</p>
                </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 变量引用中,有 $ 前缀。

Edit 2: It looks like SLQ-Server is not a fully complaint XQuery processor...

So, a more "static" XQuery (wich is fine is the schema is well known):

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
             }
   }
}

With this parameters (With SQL-Server you could also use sql:variable() extension function):

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

Output:

<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>
          <p>Pedro de Valdivia 291</p><p>Providencia</p><p>Santiago</p>
                </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>

EDIT 3: I think that the correct syntax for your query in comments is:

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
             }
   }
}
')

Note: In XQuery variable reference have $ prefixed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文