Sql server 在SQL Server XML处理中参数化modify()的XPath
正如标题所示,我试图为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
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”)
,这将是一个很好的解决方案,但不幸的是,在这种情况下,我有任意数量的级别,因此它似乎会使它变得松散。我想,除非我找到另一个好的答案,否则我将使用动态查询,尽管出于安全考虑我对此有所保留。谢谢你的帮助!看到您使用的本地名称(.)
函数对我帮助很大。