我有一个SQL函数,它接受一个名为的变量attribute,这是我想从中获取值的xml属性.xmlPath是完整的XML字符串.
我的xml看起来像这样:
<EventSpecificData>
<Keyword>
<Word>myWord</Word>
<Occurences>1</Occurences>
<Context>context</Context>
</Keyword>
</EventSpecificData>
Run Code Online (Sandbox Code Playgroud)
我想获取值<Word>,所以我传入/Keyword/Word并设置一个变量:
set @value = @xmlPath.value('(/EventSpecificData/@attribute)[1]', 'varchar(max)')
Run Code Online (Sandbox Code Playgroud)
但是,我不认为@attribute实际上是插入变量字符串.还有另一种方法吗?
Mik*_*son 15
以下是一些适合您的解决方案.
样本数据:
declare @xml xml
set @xml =
'<EventSpecificData>
<Keyword>
<Word>myWord</Word>
<Occurences>1</Occurences>
<Context>context</Context>
</Keyword>
</EventSpecificData>'
Run Code Online (Sandbox Code Playgroud)
无论父母如何,从名为Word的节点获取第一个值.用于//进行深度搜索并使用local-name()以匹配节点名称.
declare @Attribute varchar(max)
set @Attribute = 'Word'
select @xml.value('(//*[local-name() = sql:variable("@Attribute")])[1]', 'varchar(max)')
Run Code Online (Sandbox Code Playgroud)
使用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)')
Run Code Online (Sandbox Code Playgroud)
由于参数nodes必须是字符串文字,因此它邀请使用动态sql来解决此问题.它可能看起来像这样使它与原始变量内容一起使用.
set @Attribute = 'Keyword/Word'
declare @SQL nvarchar(max)
set @SQL = 'select @xml.value(''(/EventSpecificData/'+@Attribute+')[1]'', ''varchar(max)'')'
exec sp_executesql @SQL, N'@xml xml', @xml
Run Code Online (Sandbox Code Playgroud)
但是你应该知道,如果你使用它,你会对SQL注入攻击持开放态度.一些狡猾的最终用户可能会想出一个如下所示的属性字符串:
set @Attribute = 'Keyword/Word)[1]'', ''varchar(max)'') select @@version --'
Run Code Online (Sandbox Code Playgroud)
使用它执行动态SQL将为您提供两个结果集.该select @@version是只是为了显示一些无害的代码,但它可能会在那里有更糟糕的东西.
您可以使用quotename()来防止SQL注入攻击.它至少会阻止我的尝试.
set @Attribute = 'Keyword/Word'
set @SQL = 'select @xml.value('+quotename('(/EventSpecificData/'+@Attribute+')[1]', '''')+', ''varchar(max)'')'
exec sp_executesql @SQL, N'@xml xml', @xml
Run Code Online (Sandbox Code Playgroud)
最后一个版本使用quotename()安全吗?看看Erland Sommarskog 的这篇文章动态SQL的诅咒和祝福.
引用:
因此,使用quotename()和quotestring(),我们是否可以像使用参数化命令一样保护SQL注入?也许.我不知道有任何方法可以通过quotename()或quotestring()来填充SQL.然而,您正在将用户输入插入到SQL字符串中,而使用参数化命令则不会.
| 归档时间: |
|
| 查看次数: |
16409 次 |
| 最近记录: |