CFQUERYPARAM not working in ColdFusion 10

2019-08-12 03:19发布

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?

3条回答
地球回转人心会变
2楼-- · 2019-08-12 03:30

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楼-- · 2019-08-12 03:43

SELECT TOP #val(LOCAL.RecordsToReturn)#

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

查看更多
劫难
4楼-- · 2019-08-12 03:43

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

查看更多
登录 后发表回答