执行数据库查询时出错(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>
.
进一步相关阅读(来自我的博客):
我正在尝试使用 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>
.
进一步相关阅读(来自我的博客):