简体   繁体   中英

Error Executing Database Query (issue with WHERE clause?)

I'm trying to build a Query using CF variables for the FIELDS and WHERE clause.

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. I've confirmed that the #strFlds# portion works fine as a variable, but it seems to be choking on the #strWhere# portion. Is there a problem using a variable for the WHERE clause? (If it matters, the datasource is an SQL-Server database).

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

Your best best it to move your where statement variables into 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:

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

This has both SQL in it: WHERE SCHYEAR = and a value: '#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.

What you need to do is pass your values as parameters to the DB driver. One does this by separating the values out from where they will ultimately be used in the SQL statement. @Chris has already shown you one way to do this with an inline <cfqueryparam> tag. That's the only way to do it if you use <cfquery> tags.

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:

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

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. I've raised a ticket for this, which you might like to go vote for: Separate parameters from SQL in <cfquery> .

Further relevant reading (from my blog):

Instead of building query using variables you should create the query string inside cfquery itself. 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. 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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