执行数据库查询时出错(WHERE子句出现问题?)

时间:2015-05-19 18:43:12

标签: sql-server-2008 coldfusion

我正在尝试使用CF变量为FIELDS和WHERE子句构建查询。

我使用以下代码收到“执行数据库查询时出错”。当我渲染CF变量以给出文字,然后将查询主体基于结果文字时,一切正常。我已经确认#strFlds#部分可以正常工作,但它似乎在#strWhere#部分窒息。使用WHERE子句的变量是否有问题? (如果重要,数据源是SQL-Server数据库)。

    <cfset strWhere = " WHERE SCHYEAR = '#Form.yrVal#'">
    <cfset strFlds = "T1, T2">

    <cfquery name="qryFld" datasource="TSQL">
           SELECT #strFlds# FROM TABLE1 #strWhere#
    </cfquery>

3 个答案:

答案 0 :(得分:5)

您最有可能遇到阻止SQL注入的CF安全功能。

最好将where语句变量移动到cfqueryparams。

SELECT #strFlds#
FROM Table1
WHERE SCHYear = <cfqueryparam value="#form.yrVal#" cfsqltype="cf_sql_varchar">

答案 1 :(得分:5)

这是因为你构建SQL语句的方式是你在SQL本身中有硬编码的值,即:

WITH s
     AS (SELECT *,
                COUNT(CASE
                        WHEN [Flag] <> 'C' THEN 1
                      END)
                  OVER(
                    PARTITION BY [Item] ) AS NonC_Count
         FROM   Stationery)
SELECT Item,
       Date,
       Flag
FROM   s
WHERE  [Flag] <> 'C'
        OR NonC_Count = 0; 

其中包含SQL:<cfset strWhere = " WHERE SCHYEAR = '#Form.yrVal#'"> 和值WHERE SCHYEAR =。一个人不应该真的这样做,事实上,当你的价值观进一步嵌入表达式中时,ColdFusion会不顾一切地混淆它,以便降低SQL注入的风险(如果你是将来自'#Form.yrVal#'的值直接传递到数据库中。这是真正的不良做法。

您需要做的是将值作为参数传递给数据库驱动程序。一种方法是将值与SQL语句中最终使用的值分开。 @Chris已经通过内联form标记向您展示了一种方法。如果您使用<cfqueryparam>标签,这是唯一的方法。

如果您正在使用ColdFusion 11(总是确保在此处提出问题时指定使用的CF版本,顺便说一句),那么您可以在SQL中使用占位符作为参数:

<cfquery>

如果您使用的是CF9-10,那么使用Query.cfc可以实现同样的功能。

<cfset qryFld = queryExecute("
    SELECT #strFlds# FROM TABLE1 WHERE SCHYEAR = ?
", [{value=Form.yrVal, cfsqltype="CF_SQL_VARCHAR"}])>

使用qryFld = new Query( sql = "SELECT #strFlds# FROM TABLE1 WHERE SCHYEAR = ?", parameters = [{value=Form.yrVal, cfsqltype="CF_SQL_VARCHAR"}] ).execute().getResult(); 以这种方式完全从SQL中去除值是不可能的,这在实现上有点不足。我为此提出了一张票,你可能会投票给我:Separate parameters from SQL in <cfquery>

进一步相关阅读(来自我的博客):

答案 2 :(得分:1)

您应该在cfquery内部创建查询字符串,而不是使用变量构建查询。而且如果你想创建查询字符串动态的各个部分,你总是可以使用条件语句。就像Chris建议总是尝试使用cfqueryparam来传递值来查询。像这样。

<cfquery name="xyz" datasource="abc">
     SELECT 
         <cfif condition>
              col1
         </cfif>
         <cfif condition>
              , col2
         </cfif>
    FROM TABLE1 
    WHERE 1=1
        <cfif condition>
              AND col1 = <cfqueryparam value="#form.formfield1#" cfsqltype="cf_sql_varchar">
        </cfif>
        <cfif condition>
             AND col2 = <cfqueryparam value="#form.formfield12#" cfsqltype="cf_sql_varchar">
        </cfif>
</cfquery>