这里有几个解决方案适合您。
的样本数据:
declare @xml xml
set @xml =
'<EventSpecificData>
<Keyword>
<Word>myWord</Word>
<Occurences>1</Occurences>
<Context>context</Context>
</Keyword>
</EventSpecificData>'
获取从节点的第一个值命名的Word,无论父母。使用//
进行深度搜索,并使用local-name()
来匹配节点名称。
declare @Attribute varchar(max)
set @Attribute = 'Word'
select @xml.value('(//*[local-name() = sql:variable("@Attribute")])[1]', 'varchar(max)')
在两个级别中使用local-name()
在单独的变量中提供父节点名称和属性。
declare @Node varchar(max)
declare @Attribute varchar(max)
set @Attribute = 'Word'
set @Node = 'Keyword'
select @xml.value('(/EventSpecificData
/*[local-name() = sql:variable("@Node")]
/*[local-name() = sql:variable("@Attribute")])[1]', 'varchar(max)')
由于参数nodes
必须是一个字符串字面它邀请使用动态SQL来解决这个问题。它可能看起来像这样,使它与你的原始可变内容一起工作。
set @Attribute = 'Keyword/Word'
declare @SQL nvarchar(max)
set @SQL = 'select @xml.value(''(/EventSpecificData/'[email protected]+')[1]'', ''varchar(max)'')'
exec sp_executesql @SQL, N'@xml xml', @xml
但如果你使用这个,你应该知道,你是敞开的SQL注入攻击。一些狡猾的最终用户可能会拿出一个属性字符串,看起来像这样:
set @Attribute = 'Keyword/Word)[1]'', ''varchar(max)'') select @@version --'
执行动态SQL与会给你两个结果集。 select @@version
只是在那里显示一些无害的代码,但它可能是更糟糕的东西在那里。您可以使用quotename()
来防止SQL注入攻击。它至少会阻止我所做的尝试。
set @Attribute = 'Keyword/Word'
set @SQL = 'select @xml.value('+quotename('(/EventSpecificData/'[email protected]+')[1]', '''')+', ''varchar(max)'')'
exec sp_executesql @SQL, N'@xml xml', @xml
是最后的版本使用quotename()
安全吗?看看这篇由Erland Sommarskog The Curse and Blessings of Dynamic SQL发表的文章。
报价:
与QUOTENAME()和quotestring()
那么,我们是否有良好的保护 针对SQL注入,因为我们有与参数化的命令?也许。 I 不知道任何注入quotename()或者quotestring()的SQL的注入方式。尽管如此,您正在将用户输入插入到 SQL字符串中,而使用参数化命令则不然。
我不认为你可以这样做 - SQL XQuery经常使用字面字符串,而且大多数情况下,它们不能用SQL变量替换.... – 2012-02-10 16:53:19