CFQUERYPARAM not working in ColdFusion 10

2019-08-12 02:50发布

问题:

I am passing three integers into a function in a CFC, like this:

<cfscript>
Q = TOPBIKES.GetTopBikes(127, 10, 11);
writeDump(Q);
</cfscript>

The CFC uses these integers to run a query like this:

<!--- GET TOP BIKES --->
<cffunction name="GetTopBikes">
    <cfargument name="FeatureID" required="true">
    <cfargument name="MinWins" required="true">
    <cfargument name="RecordsToReturn" required="true">
    <cfscript>
        LOCAL.FeatureID = ARGUMENTS.FeatureID;
        LOCAL.MinWins = ARGUMENTS.MinWins;
        LOCAL.RecordsToReturn = ARGUMENTS.RecordsToReturn;
    </cfscript>
    <!--- RUN QUERY --->        
    <cfquery name="Q">
        SELECT      TOP #LOCAL.RecordsToReturn#
                    B.BikeID, 
                    B.BikeName,
                    BS.PCTWins
        FROM        Bikes B
                    LEFT JOIN BikeScores BS
                        ON B.BikeID = BS.BikeID
        WHERE       BS.Wins > <cfqueryparam cfsqltype="cf_sql_integer" value="#LOCAL.MinWins#">
                    AND B.BikeID IN (   SELECT  BikeID
                                        FROM    Bikes_Features
                                        WHERE   FeatureID = <cfqueryparam cfsqltype="cf_sql_integer" value="#LOCAL.FeatureID#">
                                    )   
        ORDER BY    BS.PCTWins desc
    </cfquery>
    <cfreturn Q>
</cffunction>

The problem is that I cannot get cfqueryparam to work in the TOP part of the SQL statement.

These work:

SELECT      TOP 11
SELECT      TOP #LOCAL.RecordsToReturn#

This does not work:

SELECT      TOP <cfqueryparam 
                  cfsqltype="cf_sql_integer" 
                  value="#LOCAL.RecordsToReturn#">

I can, however use anywhere else in the query. I know it's an integer and works when used elsewhere such in replacement of the FeatureID.

Any clue as to why CFQUERYPARAM is not working in TOP?

回答1:

SELECT TOP #val(LOCAL.RecordsToReturn)#

Some parts of a SQL statement cannot use cfqueryparam, such as Top or table name after From.



回答2:

The thing to remember - and Peter's notes that you link to don't explicitly say this, Evik - is that there's two parts to an SQL statement: the SQL "commands", and the data being used by the SQL commands. Only the data can be parameterised. If you think about it, that makes sense: the SQL commands themselves are not "parameters".

One can think in a CF context here, for an analogy. Consider this statement:

<cfset variables.foo = "bar">

One could "parameterise" this with a passed-in value:

<cfset variables.foo = URL.foo>

(Where URL.foo is a parameter in this example)

But one could not expect to do this:

<#URL.tag# variables.foo = "bar">

(this is a very contrived example, but it demonstrates the point).

I think as far as the SQL in a <cfquery> goes, the waters are muddied somewhat because the whole thing is just a string in CF, and any part of the string can be swapped-out with a variable (column names, boolean operators, entire clauses, etc). So by extension one might think any variable can be replaced with a <cfqueryparam>. As we know now, this is not the case, as whilst it's all just a string as far as CF is concerned, it's considered code to the DB, so needs to conform to the DB's coding syntax.

Does this clarify the situation more?



回答3:

new syntax for MS SQL (from 2005): select top(10) ... for 10 you can have cfqueryparam.