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?
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:
One could "parameterise" this with a passed-in value:
(Where URL.foo is a parameter in this example)
But one could not expect to do this:
(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?
SELECT TOP #val(LOCAL.RecordsToReturn)#
Some parts of a SQL statement cannot use cfqueryparam, such as Top or table name after From.
new syntax for MS SQL (from 2005): select top(10) ... for 10 you can have cfqueryparam.