简体   繁体   English

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

[英]Error Executing Database Query (issue with WHERE clause?)

I'm trying to build a Query using CF variables for the FIELDS and WHERE clause. 我正在尝试使用CF变量为FIELDS和WHERE子句构建查询。

I'm getting an "Error Executing Database Query" with the following code. 我正在使用以下代码获得“执行数据库查询时出错”。 When I render the CF variables to give a literal, and then base the Query body on the resulting literal, everything works fine. 当我渲染CF变量以给出文字,然后将查询主体基于结果文字时,一切正常。 I've confirmed that the #strFlds# portion works fine as a variable, but it seems to be choking on the #strWhere# portion. 我已经确认#strFlds#部分可以正常工作,但它似乎在#strWhere#部分窒息。 Is there a problem using a variable for the WHERE clause? 使用WHERE子句的变量是否有问题? (If it matters, the datasource is an SQL-Server database). (如果重要,数据源是SQL-Server数据库)。

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

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

You are most likely running into a security feature of CF that prevents SQL injection. 您最有可能遇到阻止SQL注入的CF安全功能。

Your best best it to move your where statement variables into cfqueryparams. 最好将where语句变量移动到cfqueryparams中。

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

It's because the way you're building your SQL statement you've got values hard-coded amongst the SQL itself, ie: 这是因为你构建SQL语句的方式是你在SQL本身中有硬编码的值,即:

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

This has both SQL in it: WHERE SCHYEAR = and a value: '#Form.yrVal#' . 这里面有两个SQL: WHERE SCHYEAR =和一个值: '#Form.yrVal#' One shouldn't really do that, and indeed when your values are further embedded within an expression, ColdFusion goes out of its way to mess with it so as to reduce the risk of SQL injection (which you're ripe for if you're passing values sourced from a form directly into the DB. This is really bad practice. 一个人不应该真的这样做,事实上,当你的价值观进一步嵌入表达式中时,ColdFusion会不顾一切地混淆它,以便降低SQL注入的风险(如果你是将源自form值直接传递给DB。这是非常糟糕的做法。

What you need to do is pass your values as parameters to the DB driver. 您需要做的是将值作为参数传递给DB驱动程序。 One does this by separating the values out from where they will ultimately be used in the SQL statement. 一种方法是将值与SQL语句中最终使用的值分开。 @Chris has already shown you one way to do this with an inline <cfqueryparam> tag. @Chris已经通过内联<cfqueryparam>标记向您展示了一种方法。 That's the only way to do it if you use <cfquery> tags. 如果您使用<cfquery>标签,这是唯一的方法。

If you are using ColdFusion 11 (always make sure to specify which version of CF you're using when you raise a question here, btw), then you can use placeholders for parameters in your SQL, thus: 如果您正在使用ColdFusion 11(始终确保在此处提出问题时指定使用的CF版本,顺便说一句),那么您可以在SQL中使用占位符作为参数,因此:

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

If you're using CF9-10, then the same sort of thing is achievable using Query.cfc. 如果您使用的是CF9-10,那么使用Query.cfc可以实现同样的功能。

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

It's not possible to completely decouple the values from the SQL in this way using <cfquery> , which is a bit of a shortfall in its implementation. 使用<cfquery>以这种方式完全将SQL与SQL分离是不可能的,这在实现上有点不足。 I've raised a ticket for this, which you might like to go vote for: Separate parameters from SQL in <cfquery> . 我已经为此提出了一张票,你可能想投票给它: <cfquery>从SQL中分离参数

Further relevant reading (from my blog): 进一步相关阅读(来自我的博客):

Instead of building query using variables you should create the query string inside cfquery itself. 您应该在cfquery本身内部创建查询字符串,而不是使用变量构建查询。 And any way if you want to create the various part of the query string dynamic, you can always use conditional statements. 而且如果你想创建查询字符串动态的各个部分,你总是可以使用条件语句。 And like Chris suggested always try to use cfqueryparam for passing values to query. 和Chris建议总是尝试使用cfqueryparam将值传递给查询。 Like this. 像这样。

<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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM