2015-11-06 31 views
2

在我的ColdFusion 11的應用程序,使用SQL Server 2008 R2,我下面一個CF組件內CFQUERY標籤:ColdFusion的單引號問題與SQL查詢

<cfquery name="result_set" dataSource="#request.dsn_name#"> 
    select name, state from myTable #REReplace(where_clause,"''","'","ALL")#   
</cfquery> 

這裏where_clause是一個變量。 CF用兩個單引號替換,因此我使用REReplace函數將兩個單引號替換爲一。所以我的查詢會改變,例如從

select name, state from myTable WHERE name IN (''ABC'') 

這樣:

select name, state from myTable WHERE name IN ('ABC') 

問題是,當一個名字列值包含一個單引號爲好。例如。

select name, state from myTable WHERE name IN ('Smith's bat') 

在這種情況下查詢失敗。我該如何解決這些問題。我嘗試了PreserveSingleQuotes,但它具有相同的問題,其中列的值使用單引號。

UPDATE

這個程序使用的ColdFusion MX 7原作者是創建基於某些條件where_clause變量動態字符串開發年前由一個人。這是一個很長的cfs文件,有幾個條件用於爲where_clause創建動態字符串。因此,使用cfqueryparam可能不合適,或者可能需要徹底檢查客戶不允許的代碼。

+5

更好的方法是重寫查詢以使用參數('')。這樣做會非常容易出錯,並可能導致[** SQL注入**](https://www.owasp.org/index.php/SQL_Injection)漏洞。 –

+5

...並且是您首先遇到查詢問題的原因。不要使用那種動態sql。相反,在cfquery中構建sql並在所有參數上使用cfqueryparam(或者查看使用cfscript查詢,這爲「參數化」sql提供了更多的靈活性)。這既能保護數據庫,又能消除這種類型的錯誤。 – Leigh

+4

如果你想堅持在''調用之外創建你的SQL字符串,可以使用'queryExecute()'來代替它,它允許你將參數佔位符放入SQL字符串中;然後將參數值傳遞給單獨的數組/結構。只是*不要*將值硬編碼到SQL字符串中。這是可怕的,尷尬的,危險的。 –

回答

1

這是一個討厭的問題。恐怕我只能想出一個討厭的「解決方案」。

  • 替代值分隔符:<cfset where_clause = replace(where_clause, "''", "§§", "ALL")>
  • 然後逃逸的實際單引號:<cfset where_clause = replace(where_clause, "'", "\'", "ALL")>
  • 現在恢復替代和規範分隔符:<cfset where_clause = replace(where_clause, "§§", "'", "ALL")>

一起把它扔:

<cfset substitution = "§§"> <!--- use whatever char sequence works best for your data ---> 

<!--- fallback in case the substitution is part of your data ---> 
<cfif where_clause contains substitution> 

    <cfset substitution = "°°°"> 
    <!--- 
     you can basically start looping through a bunch of alternatives 
     or even expand the substition with an additional character 
     ...you get the idea 
    ---> 

</cfif> 

<cfset where_clause = replace(where_clause, "''", substitution, "ALL")> 
<cfset where_clause = replace(where_clause, "'", "\'", "ALL")> 
<cfset where_clause = replace(where_clause, substitution, "'", "ALL")> 

<cfquery... 

正如你所見,這仍然是高度問題,並可能在一天失敗。但只要你必須處理where_clause變量,可能沒有更好的選擇。

0

您需要使用的功能PreserveSingleQuotes,這種方式:

<cfquery name="result_set" dataSource="#request.dsn_name#"> 
    select name, state from myTable #PreserveSingleQuotes(REReplace(where_clause,"''","'","ALL"))#   
</cfquery> 

有一個好的一天!

+0

@PauloTexeira。您的建議會給出錯誤信息:'函數PreserveSingleQuotes'不支持複雜結構' – nam

+0

打印字符串的cfdump以幫助我們理解數據。 –

+0

請記住,只有在單引號正確轉義的情況下才有效,而不是(從OP中判斷)。從個人經驗來看,這種動態sql極其容易出錯,並且極其痛苦,無法調試...更不用說它將數據庫全部公開給sql注入。儘管可以使其工作,但切換到「參數化」查詢是更安全和更理想的IMO選項 – Leigh