Cannot Use ColdFusion CFQueryParam With SQL TOP Directive

Posted January 10, 2007 at 12:36 PM by Ben Nadel

Tags: ColdFusion, SQL

I just came across a strange little error that took me a few minutes to debug. I was running this SQL query:

  • DELETE FROM
  • reward
  • WHERE
  • order_id = 0
  • AND
  • delivery_id = <cfqueryparam value="#id#" cfsqltype="CF_SQL_INTEGER" />
  • AND
  • id IN
  • (
  • SELECT TOP <cfqueryparam value="#(qUnused.reward_count - FORM.quantity)#" cfsqltype="CF_SQL_INTEGER" />
  • id
  • FROM
  • reward
  • WHERE
  • order_id = 0
  • AND
  • delivery_id = <cfqueryparam value="#id#" cfsqltype="CF_SQL_INTEGER" />
  • ORDER BY
  • id DESC
  • )

... and it was throwing this error:

[Macromedia][SQLServer JDBC Driver][SQLServer]
Line 11: Incorrect syntax near '@P2'.

Looking at the debugging SQL:

  • DELETE FROM
  • reward
  • WHERE
  • order_id = 0
  • AND
  • delivery_id = (param 1)
  • AND
  • id IN
  • (
  • SELECT TOP (param 2)
  • id
  • FROM
  • reward
  • WHERE
  • order_id = 0
  • AND
  • delivery_id = (param 3)
  • ORDER BY
  • id DESC
  • )

... I can see that Param 2 is the SQL TOP value. Going in and take the CFQueryParam out and replace it with:

  • SELECT TOP #(qUnused.reward_count - FORM.quantity)#

... things work just fine. Apparently, you cannot use the CFQueryParam with the SQL TOP statement. Not sure what this is all about. It seems like this is a place where SQL injection could occur (especially in my case where the TOP value is being derived from a FORM value). Perhaps this is just not the best way for me to accomplish this goal.



Reader Comments

Jan 10, 2007 at 1:28 PM // reply »
15 Comments

There was a bug in recent updates to CF that caused using Maxrows on a query to be problematic. I went changing some old queries that used the maxrows to use top instead and came across this as well. I don't think this is a CF but rather a MS SQL issue.


Jan 10, 2007 at 1:29 PM // reply »
15 Comments

There was a bug in recent updates to CF that caused using Maxrows on a query to be problematic. I went changing some old queries that used the maxrows to use top instead and came across this as well. I don't think this is a CF but rather a MS SQL issue.


Jan 10, 2007 at 1:31 PM // reply »
15 Comments

Sorry my comment got posted twice, but FYI I got a 500 null error when I submitted it both times and didn't think it went through...also I checked remember my information and it does not seem to have done so. Just letting you know.


Jan 10, 2007 at 2:33 PM // reply »
10,640 Comments

Thanks for letting me know. Something has gone a bit cookey with the comment posting in the last few days. I have to figure out what happened. I am on it!


Jan 10, 2007 at 2:48 PM // reply »
10,640 Comments

Ok I made an update to the comment. Please let me know if anything goes wrong again.

Thanks!


Jan 10, 2007 at 2:49 PM // reply »
48 Comments

How about this Ben? Before the query do:

declare @param int
set @param = <cfqueryparam value="#id#" cfsqltype="CF_SQL_INTEGER" />

then in your query do a:

select top @param......

not tested, but should work....


Jan 10, 2007 at 2:50 PM // reply »
48 Comments

OK i lied - maybe it doesn't work...


Jan 10, 2007 at 2:53 PM // reply »
10,640 Comments

Todd,

Nice thought. I guess it just can't handle binding in general? As Brian says above, at least it's not a ColdFusion error, but one of the SQL server.


Jan 10, 2007 at 3:00 PM // reply »
48 Comments

If it's that important, you could always make the sql dynamic like this:

DECLARE @param int
set @param = <cfqueryparam value="#id#" cfsqltype="CF_SQL_INTEGER" />

DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT top ' + @param + 'columns and stuff'+
' FROM ...' +
' WHERE...'

EXEC sp_executesql @sql


Jan 10, 2007 at 3:01 PM // reply »
48 Comments

That one WAS tested ;)


Jan 10, 2007 at 3:06 PM // reply »
15 Comments

In general, unless it is completely necessary, I avoid dynamic sql like that. The reason is that it is my understanding that when using dynamic sql like that MS SQL recompiles the execution plan on every request - so it would negate the performance benefit of using the queryparam to create a prepared statement I believe. This would also be the case even if your dynamic SQL was in a stored procedure...execution plan is recreated on each call...


Jan 10, 2007 at 3:08 PM // reply »
10,640 Comments

Todd,

Sorry, that goes way beyond my understanding. I mean, I get what you are doing, but I know zero about dynamic SQL execution :)


Jan 10, 2007 at 3:19 PM // reply »
48 Comments

What about this Brian/Ben?

<cfquery...>
set rowcount <cfqueryparam value="1" cfsqltype="cf_sql_integer">
select *
from tbl...
where stuff...
set rowcount 0
</cfquery>

Would this cache the execution plan? It solves the TOP n issue, and it works...


Jan 10, 2007 at 3:21 PM // reply »
48 Comments

Though I would be nervous doing that with a delete...


Jan 10, 2007 at 3:22 PM // reply »
48 Comments

sorry for being a comment wh*re...


Jan 10, 2007 at 4:49 PM // reply »
160 Comments

I would imagine the reason it doesn't work is you can't bind a variable to the TOP directive.

Why not just use:

SELECT TOP #val(qUnused.reward_count - val(trim(FORM.quantity)))#

This should prevent SQL Injections and the val() function will make sure your value is seen as an integer.


Jan 10, 2007 at 5:04 PM // reply »
10,640 Comments

@Todd,

No worries on being a wh*re ;) Comments rock. Thinking out-loud rocks.

@Dan,

Nice tip on Val().

Good stuff all around.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 12, 2012 at 3:37 AM
Learning ColdFusion 8: CFImage Part III - Watermarks And Transparency
Hi Ben, Just to ask currently it is placed bottom right corner, if i need to replace the same rendered image on the bottom left side or in the bottom center, how that can be calculated. bottom ce ... read »
Feb 11, 2012 at 9:29 PM
Use jQuery's SlideDown() With Fixed-Width Elements To Prevent Jumping
I can't say how glad I am that I found your post. Thank you very much. ... read »
Feb 10, 2012 at 7:21 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
Update! Instead of $(eval(options.insertAfter)).after(data['insertData']); I now use: var ajaxNode = document.createElement('span'); var parent = $(eval(options.insertAfter))[0].parentNode; ... read »
Feb 10, 2012 at 6:18 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
encountered this same, what I consider, jQuery bug last week. I'm building a site in which I load some content via AJAX. This content contains Linkedin share button placeholders which Linkedin API ne ... read »
Feb 10, 2012 at 11:30 AM
Cross-Origin Resource Sharing (CORS) AJAX Requests Between jQuery And Node.js
After you understand the concepts here, this is an awesome cheatsheet for enabling CORS in just about anything http://enable-cors.org/ ... read »
JM
Feb 10, 2012 at 9:10 AM
My Safari Browser SQLite Database Hello World Example
@Amy, Here is a very good tutorial on how to use JOIN: http://www.sqltutorial.org/sqljoin-innerjoin.aspx ... read »
Feb 10, 2012 at 4:42 AM
Building A Twitter-Inspired RESTful API Architecture In ColdFusion
This is great, very useful Ben. I spotted a small typo in the api.cgm listing: <cfthrow type="Unauthroized" /> Cheers Stefan ... read »
Feb 9, 2012 at 10:35 PM
CFDirectory Filtering Uses Pipe Character For Multiple Filters (Thanks Steve Withington)
I was wondering if there would be a filter you could apply so that you got everything but what you included in the filter. As in show me all docs that are not a .pdf. ... read »