Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL Server XML处理中参数化modify()的XPath_Sql Server_Xml_Xpath - Fatal编程技术网

Sql server 在SQL Server XML处理中参数化modify()的XPath

Sql server 在SQL Server XML处理中参数化modify()的XPath,sql-server,xml,xpath,Sql Server,Xml,Xpath,正如标题所示,我试图为SQL Server中的XML数据列的modify()方法参数化XPath,但遇到了一些问题 到目前为止,我已经: DECLARE @newVal varchar(50) DECLARE @xmlQuery varchar(50) SELECT @newVal = 'features' SELECT @xmlQuery = 'settings/resources/type/text()' UPDATE [dbo].[Users] SET [SettingsXml

正如标题所示,我试图为SQL Server中的XML数据列的modify()方法参数化XPath,但遇到了一些问题

到目前为止,我已经:

DECLARE @newVal varchar(50)
DECLARE @xmlQuery varchar(50)
SELECT @newVal = 'features'
SELECT @xmlQuery = 'settings/resources/type/text()'

UPDATE  [dbo].[Users]
SET     [SettingsXml].modify('
    replace value of (sql:variable("@xmlQuery"))[1]
    with sql:variable("@newVal")')
WHERE   UserId = 1
使用以下XML结构:

<settings>
    ...
    <resources>
        <type> ... </type>
        ...
    </resources>
    ...
</settings>

...
... 
...
...
然后生成此错误:

XQuery[dbo.Users.NewSettingsXml.modify()]:“replace”的目标最多只能是一个节点,找到“xs:string?”

现在我意识到modify方法不能接受字符串作为路径,但是有没有一种方法可以实现动态SQL的这种缺陷呢

哦,顺便说一句,我使用的是SQL Server 2008标准64位,但我编写的任何查询都需要与2005标准兼容


谢谢

我能想到的最好办法是:

declare @Q1 varchar(50)
declare @Q2 varchar(50)
declare @Q3 varchar(50)
set @Q1 = 'settings'
set @Q2 = 'resources'
set @Q3 = 'type'

UPDATE  [dbo].[Users]
SET     [SettingsXml].modify('
    replace value of (for $n1 in /*,
                          $n2 in $n1/*,
                          $n3 in $n2/*
                      where $n1[local-name(.) = sql:variable("@Q1")] and
                            $n2[local-name(.) = sql:variable("@Q2")] and
                            $n3[local-name(.) = sql:variable("@Q3")]
                      return $n3/text())[1]
    with sql:variable("@newVal")')
WHERE   UserId = 1

节点名称是参数,但遗憾的是节点的级别/数量不是参数。

如果有人感兴趣,我自己使用动态查询提出了一个相当不错的解决方案:

DECLARE @newVal nvarchar(max)
DECLARE @xmlQuery nvarchar(max)
DECLARE @id int

SET @newVal = 'foo'
SET @xmlQuery = '/root/node/leaf/text()'
SET @id = 1

DECLARE @query nvarchar(max)

SET @query = '
    UPDATE  [Table]
    SET     [XmlColumn].modify(''
        replace value of (' + @xmlQuery + '))[1]
        with sql:variable("@newVal")'')
    WHERE Id = @id'

EXEC sp_executesql @query,
                   N'@newVal nvarchar(max) @id int',
                   @newVal, @id

使用它,动态查询中唯一不安全的部分是xPath,在我的例子中,xPath完全由我的代码控制,因此不应该被利用。

下面是我们找到的用于参数化要替换的属性名和新值的解决方案。它需要一个特定的xpath,参数名可以是sql变量或表列

SET Bundle.modify
(
  'replace value of(//config-entry-metadata/parameter-name[text() = sql:column("BTC.Name")]/../..//value/text())[1] with sql:column("BTC.Value") '
)
这是硬编码的x路径:
//配置条目元数据/参数名称…/..///value/text()

参数的名称是动态的:
[text()=sql:column(“BTC.name”)]


新值也是动态的:
带有sql:column(“BTC.value”)

,这将是一个很好的解决方案,但不幸的是,在这种情况下,我有任意数量的级别,因此它似乎会使它变得松散。我想,除非我找到另一个好的答案,否则我将使用动态查询,尽管出于安全考虑我对此有所保留。谢谢你的帮助!看到您使用的
本地名称(.)
函数对我帮助很大。