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

Error Executing Database Query (issue with WHERE clause?)

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

我正在使用以下代码收到 "Error Executing Database Query"。当我呈现 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>

您很可能 运行 使用了防止 SQL 注入的 CF 安全功能。

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

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

您应该在 cfquery 本身内部创建查询字符串,而不是使用变量构建查询。无论如何,如果您想动态创建查询字符串的各个部分,您始终可以使用条件语句。就像克里斯建议的那样,始终尝试使用 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>

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

<cfset strWhere = " WHERE SCHYEAR = '#Form.yrVal#'">

其中包含 SQL:WHERE SCHYEAR = 和一个值:'#Form.yrVal#'。人们不应该真的那样做,事实上,当您的值进一步嵌入表达式中时,ColdFusion 会不遗余力地处理它,以降低 SQL 注入的风险(您已经成熟了如果您将来自 form 的值直接传递到数据库中。这 确实是 不好的做法。

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

如果您使用的是 ColdFusion 11(顺便说一下,请务必在此处提出问题时指定您使用的是哪个版本的 CF),然后您可以在 SQL 中为参数使用占位符,因此:

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

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

qryFld = new Query(
    sql = "SELECT #strFlds# FROM TABLE1 WHERE SCHYEAR = ?",
    parameters = [{value=Form.yrVal, cfsqltype="CF_SQL_VARCHAR"}]
).execute().getResult();

无法使用<cfquery>以这种方式将值与SQL完全解耦,这在其实现中有点不足。我为此提出了一张票,你可能想投票给它:Separate parameters from SQL in <cfquery>.

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