這裏有幾個解決方案適合您。
的樣本數據:
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