Ask Ben: Query Loop Inside CFScript Tags

Posted July 25, 2006 at 8:54 AM by Ben Nadel

Tags: ColdFusion, Ask Ben

I know I can loop over a query using the loop tag, but is there a way to do a query loop inside of script tags?

Yes. The ColdFusion query object is a specialized record set structure, but really you can think of it as a glorified array of sorts. The trick here lies in the fact that, like an array or structure, you can access values in a ColdFusion query through the use of keys and indexes.

This idea of key/index accessing can be used when both looping over a query and creating one from scratch. To help demonstrate this, let's start by building a small query from scratch:

  • <!--- Create a new query. --->
  • <cfset qPornStars = QueryNew( "name, sex, preferred_category" ) />
  •  
  • <!--- Add rows to this query. --->
  • <cfset QueryAddRow( qPornStars ) />
  • <cfset qPornStars[ "name" ][ 1 ] = "Jenna Jameson" />
  • <cfset qPornStars[ "sex" ][ 1 ] = "Female" />
  • <cfset qPornStars[ "preferred_category" ][ 1 ] = "Girl on Girl" />
  •  
  • <cfset QueryAddRow( qPornStars ) />
  • <cfset qPornStars[ "name" ][ 2 ] = "Peter North" />
  • <cfset qPornStars[ "sex" ][ 2 ] = "Male" />
  • <cfset qPornStars[ "preferred_category" ][ 2 ] = "Guy on Girl" />

Notice here that as we add rows to the query, we are setting cell values by directly accessing the cell positions. We are treating the query as a Struct of Arrays. Notice that the first structure notation is the name of the column and the second structure notation is the row in the record set. Together we get the exact location in the query that we wish to update.

Using that knowledge, we can easily loop over a query in a CFScript blocking using an index loop.

  • <cfscript>
  •  
  • // Loop over the records in the query.
  • for (
  • intRow = 1 ;
  • intRow LTE qPornStars.RecordCount ;
  • intRow = (intRow + 1)
  • ){
  •  
  • // Output the name some values. When doing so, access the
  • // query as if it were a structure of arrays and we want
  • // only get values from this row index.
  • WriteOutput(
  • qPornStars[ "name" ][ intRow ] & " is a " &
  • qPornStars[ "sex" ][ intRow ] & " that prefers doing " &
  • qPornStars[ "preferred_category" ][ intRow ] & " movies." &
  • "<br />"
  • );
  • }
  •  
  • </cfscript>

This will produce the following output:

Jenna Jameson is a Female that prefers Girl on Girl movies.
Peter North is a Male that prefers Guy on Girl movies.

As you can see, it takes a little more elbow grease, but looping over a query inside of a CFScript is more than doable. And as we saw above, understanding how to access query cells without CFLoop gives you the ability to build queries as well.




Reader Comments

Oct 15, 2006 at 12:50 PM // reply »
3 Comments

Thanks for the post Ben. This helped me loop through an array in cfscript.

Ryan


Oct 15, 2006 at 12:51 PM // reply »
11,314 Comments

Ryan,

Always glad to help. Yeah, when it boils down to it, there are really only two types of loops in CFScript... Index loops as you would do with an array or a query, or Collection loops as you would do with a Struct.

Drop me a line if you need help with anything else.


Jul 31, 2007 at 7:47 PM // reply »
11 Comments

What happens if Jenna comes back Girl on Girl and Girl on Guy?


Aug 1, 2007 at 7:15 AM // reply »
11,314 Comments

I don't care what happens so long as someone in the room has a video camera :D


Jan 28, 2008 at 1:27 PM // reply »
17 Comments

in cf7 at least while testing
for 46028 records,

109-125ms
<cfoutput query="qryTest">
#field1#
</cfoutput>

was faster than
172-219ms
<cfscript>
for(i=1; i lte qryGetAMFiles.recordcount; i=i+1) {
writeOutput(qryTest.field1[i] & " ");
}
</cfscript>

in 5 tests the mins/max were shown.


Feb 4, 2008 at 9:17 PM // reply »
11,314 Comments

@Steve,

I think that just goes to show you have to go with whatever you find easier / most readable. Thanks for dropping in the testing there.


Jul 6, 2008 at 11:57 AM // reply »
1 Comments

Thanks,

This is a only posting I could find that shows how to get at individual data fields from inside cfscript


Apr 17, 2009 at 5:22 PM // reply »
1 Comments

Thanks Ben... as usual, your site pulls through.


Apr 17, 2009 at 5:28 PM // reply »
11,314 Comments

@Jon,

Awesome my man, glad to help!


Jun 16, 2009 at 12:07 PM // reply »
7 Comments

Thanks Ben... as usual, your site pulls out. (get it?)


Jun 16, 2009 at 12:08 PM // reply »
11,314 Comments

@Luke,

Ha ha ha ha.


Jun 16, 2009 at 3:10 PM // reply »
17 Comments

You need to backdate our points from kinky posts :P
err, umm, our kinky points from posts.


Jun 19, 2009 at 8:00 PM // reply »
11,314 Comments

@Steve,

Yeah, at one point I just had to flip the switch. Unfortunately, I had no good way to retrofit the existing comments.


Jul 16, 2009 at 11:31 AM // reply »
1 Comments

Your example is illustrative, but using porn to illustrate it is crude. Why not use examples of alcoholics, crackheads, and child molesters to illustrate ColdFusion? Porn is disgusting.


Jul 18, 2009 at 1:49 PM // reply »
11,314 Comments

@Adam,

I don't find alcoholics, crackheads, or child molesters even remotely entertaining.


Oct 6, 2009 at 10:40 PM // reply »
1 Comments

Ben, thanks for the helpful and cool blog. You're my hero.


Nov 1, 2009 at 3:41 PM // reply »
11,314 Comments

@Grant,

Ha ha, no problem :) Glad to help.


JP
Jan 29, 2010 at 5:43 AM // reply »
1 Comments

Thanks for the help!! And long live Jenna!! :D


Mar 9, 2011 at 11:13 AM // reply »
369 Comments

Thanks. This was a lot of help for a problem I was working on for work. Now, I just have to be sure to remember to remove all the porn references. :-P


Mar 9, 2011 at 12:02 PM // reply »
11,314 Comments

@Anna,

Ha ha, no problem - glad it helped.


Mar 9, 2011 at 2:34 PM // reply »
369 Comments

Thanks! btw, would this also work, or am I WAY off with this?:

  • if(qPornStars.recordCount){
  • recCount = qPornStars.recordCount;
  • counter = 1;
  • while(counter lt recCount) {
  • WriteOutput(qPornStars[ "name" ][ intRow ] & " is a " & qPornStars[ "sex" ][ intRow ] & " that prefers doing " & qPornStars[ "preferred_category" ][ intRow ] & " movies." & "<br />");
  • }
  • counter = counter + 1;
  • }


Mar 9, 2011 at 5:02 PM // reply »
17 Comments

That is almost the same, except you are using a while loop instead of a for loop.

http://www.petefreitag.com/cheatsheets/coldfusion/cfscript/

I would reach for a better grasp of the for loop, as it is almost identical to javascript and many other languages.
Also the for loop allows you to define your starting point, condition, and iteration stepper all on the same line, so it is less lines of code.


Mar 9, 2011 at 10:50 PM // reply »
369 Comments

Thanks for the insight, Steve! I am all about best practices and doing it the best way instead of just whatever works. The reason I initially did it this way is because I am in the process of converting a site from php to ColdFusion :-), and this was the way it was done in php but I am certainly not opposed to changing it.


Mar 10, 2011 at 8:27 AM // reply »
2 Comments

Another method of looping a query in Coldfusion is to use a while loop with query.next(). Using this method eliminates the need to have an additional counter, and gives you access to the currentRow variable within the query object. While they are functionally the same, this is another option.

while (qPornStars.next()) {
qPornStars.currentRow
}


Mar 10, 2011 at 9:40 AM // reply »
369 Comments

Thanks, James! :-) So, it would be WriteOutput(qPornStars[ "name" ][ qPornStars.currentRow ]
to access it this way?

Thanks!


Mar 10, 2011 at 10:40 AM // reply »
2 Comments

Correct :)


Mar 10, 2011 at 10:54 AM // reply »
369 Comments

Thanks, James! :-)

@Ben, doesn't Evil Ben need to be the one making that comment about the camera??? >:-}

Did Evil Ben hack into your account? >:-} <~~~~my attempt at making an evil smiley :-/


Oct 28, 2011 at 3:54 AM // reply »
4 Comments

It would be super pimpin' if someone could post code for the equivalent of using the group= attribute of cfouput looping over a query. Probably need a UDF for that?


Oct 30, 2011 at 11:16 PM // reply »
17 Comments

@Chris,
You need to do the set lastval = col
If lastval neq curVal then do new groupset


Jun 17, 2012 at 9:53 PM // reply »
1 Comments

I came here because I needed the howto you provide, but before I even read it had to post this comment. Porn stars? WOW!!!! Now THAT's a way to get my full attention! You should be a school teacher!


Jun 18, 2012 at 12:03 PM // reply »
17 Comments

@Larry,

Hehe and I can totally appreciate your posting name :P Lets see how many people have to look it up!

(My friend was just showing me the open source sierra project a few minutes ago and we were reliving some 1980's glory!)


Jun 29, 2012 at 7:32 PM // reply »
43 Comments

Looks like:

  • while (qry.next()) {
  • qry.myFieldName[qry.currentRow]
  • }

works as well.


Jul 5, 2012 at 12:15 AM // reply »
4 Comments

@Phillip,

That rocks - thanks for sharing!


Mar 8, 2013 at 9:56 AM // reply »
2 Comments

Best. Example Code. EVER.


May 22, 2013 at 12:44 PM // reply »
43 Comments

In cf10, if you call a function that has:

  • local.result = {};
  • local.result.msg = "";
  • local.svc = new query();
  • local.svc.setSQL("SELECT * FROM...");
  • local.obj = local.svc.execute();
  • local.result.qry = local.obj.getResult();
  • local.result.Prefix = local.obj.getPrefix();
  • return local.result;

Then you can:

  • myStars = myComponent.myFunction();
  • for (qry in myStars.qry) {
  • writeoutput(qry.Name);
  • writeoutput(qry.Gender);
  • writeoutput(qry.preferred_category);
  • }

This has allowed me to have all my functions return the same structure (result) whether it's used for a remote (ajax) call or a regular ColdFusion call.

JavaScript will process RESULT.QRY.DATA.NAME[i] while ColdFusion will process myStars.qry.

Just don't forget:

  • param name="url.returnformat" default="json";
  • param name="url.queryformat" default="column";



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
Jun 19, 2013 at 10:41 PM
Referencing ColdFusion Query Columns In A Loop Using Both Array And Dot Notation
Burdock-roots Are you going fat day by day? You need to be good for your family and make some money too. So we bring for you a best product that helps you to be more energetic every day. You will b ... read »
Jun 19, 2013 at 9:52 PM
Working With Inherited Collections In AngularJS
I recognize the applicability of your solution, and how easy it makes to share data across multiple views or even "submodules" of rather simple application. But it seems to me that it creat ... read »
Jun 19, 2013 at 9:38 PM
Directive Link, $observe, And $watch Functions Execute Inside An AngularJS Context
@Alesei, Glad you like it. Even after working with AngularJS for months, I still get a bunch of unexpected, "$digest is already in progress". So hard to debug sometimes! ... read »
Jun 19, 2013 at 9:36 PM
Working With Inherited Collections In AngularJS
@Mike, The relationship of $scope values is definitely an interesting thing! But it's not simple - it really forces you to understand prototypal inheritance, which is not at all a simple topic! Gla ... read »
Jun 19, 2013 at 9:35 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
@Joe, Oh, super interesting! I had only thought to url-encode the signature; but I think that's because the S3 docs actually have a special NOTE telling you to do so. It would have never occurred t ... read »
Jun 19, 2013 at 9:32 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
@Richard, Glad you like! Hopefully I'll have some more interesting stuff coming. This morning, I blogged a bit more about generating the pre-signed, query string authenticated URLs; but, then deeme ... read »
Jun 19, 2013 at 9:31 PM
Filter vs. ngHide With ngRepeat In AngularJS
@Mike, Honestly, in the majority of cases, I would say there isn't going to be a difference. Both approaches have trade-offs. If you use the filter, then you have fewer DOM elements and fewer $scop ... read »
Jun 19, 2013 at 2:01 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
I have coincidentally been beating my head against the S3 API for the last week or so. One big "gotcha" I had to work around was file names and paths containing spaces. Remember to URL Enco ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools