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 »
11,235 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 »
11,235 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 »
11,235 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 »
11,235 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 »
170 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 »
11,235 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
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools