to cfqueryparam or not to cfqueryparam

Most of us who have been using CF for any significant period of time are pretty familiar with the syntax of a SQL Query.

SELECT *
FROM tableName
WHERE column1 = ?#myValue#?

As of ColdFusion 4.5 (and remaining in MX), a new tag called <cfqueryparam> was introduced. I think it?s a given that this tag is not used by nearly as many CF developers as it should be (it should be used by all of them).

But why, CJ? I?m used to the simple query above. Why should I have to add more typing by doing:

SELECT *
FROM tableName
WHERE column1 = <cfqueryparam value=?#myValue#? cfsqltype=?cf_sql_char?>

Excellent question. Glad you asked. Otherwise I?d have nothing more to say, and this tutorial would be even more boring than it currently is.

Two good reasons to use <cfqueryparam>:

1) Added Security
2) Efficiency (speed) of queries

Let?s take a look at number 1 first:

Added Security

Have you ever passed a value via a URL (such as an ID) that became the value used in the WHERE clause of your query?

If you have http://www.mysite.com/page.cfm?itemID=4 as a URL, you?d probably expect a query on that page that looks something like this:

SELECT *
FROM tableName
WHERE idColumn = #URL.itemID#

What could possibly be unsecure about that? How can some malicious person hurt me or my site with that query? Simple. Some databases allow multiple SQL statements separated by a semi-colon. For example:

SELECT *
FROM tableName
WHERE column1 = ?#myValue#?; DROP TABLE tableName

Once this query selects the appropriate data, it will execute the next chunk of SQL, which will delete your table. Gone. Poof. No more table. All it takes is a semi-intelligent (and semi-malicious) user to decide he or she wants to start messing around with your database. This user would see the URL http://www.mysite.com/page.cfm?itemID=4, and could easily tack on the following: http://www.mysite.com/page.cfm?itemID=4; DROP TABLE tableName.

A longshot you say? Sure. Maybe. But do you really want to take that chance? Ask yourself what would be the consequences of your database suddenly disappearing. For many, it would be pretty close to catastrophic. 

Enter <cfqueryparam>. The cfsqltype attribute of the cfqueryparam tag specifies a datatype that is to be passed to the database. Since most ID values are numeric, the cfqueryparam would look something like this:

<cfqueryparam value=?#URL.itemID#? cfsqltype=?cf_sql_integer?>

If some unscrupulous sort were to append the DROP TABLE command to your URL parameter, the <cfqueryparam> would not execute the command (in fact, an error would be thrown, since the value of URL.itemID is no longer an integer, but now contains a string?this is where <cftry><cfcatch> and structure error handling become important).


SPEED (no, not the silly movie with the bus and the bomb)

What is it that we all want from our code? Aside from no errors?aside from the ability to generate millions of dollars because it?s the ?next big thing??.we all want speed. Our platform is the Web, and we know that if users have to wait for our code to execute on the server and display in their browser, they?re going to go elsewhere.

Here?s where <cfqueryparam> really shines. It will speed up your database queries exponentially. 

Why? 

In a ?normal? CF query, plain text is passed to the database (be it Access, SQL Server, Oracle, etc). The database must first parse that text, and ensure that the values being passed match the datatypes of the columns they reference. Any time a string needs to be parsed, time is being wasted (this is also why <cfscript> is faster than tags, and <cfif NOT structKeyExists(form, ?fieldName?)> is faster than <cfif isDefined(?form.fieldName?)>).

The use of cfqueryparam creates bind variables between your query and the database. In the most basic terms, it means that your query is handing the database the native code it expects (which would vary from db to db). As previously mentioned, this saves the db from having to parse the query string manually.

Hmmm?added security?increased speed?it sounds too good to be true! You don?t have to take my word for it. The easiest way to check for yourself is to turn debugging on in the CF Administrator for your IP Address. Run a query without the <cfqueryparam> tags, and check the execution time. Do this a few times to get an average. Then add the <cfqueryparam> tags, and repeat the process.

If you don?t have access to the CF Administrator (perhaps you?re in a shared hosting environment), you can use CF?s built in getTickCount() function.

To use getTickCount(), do the following:

<cfset beginCount = getTickCount()>

(your query here)

<cfset endCount = getTickCount()>

<cfset totalTime = endCount ? beginCount>
<cfoutput>
#totalTime#</cfoutput>

Do this first with a query that doesn?t use <cfqueryparam>, and then repeat with a query that does.

If you?re as impressed with the results as I expect you?ll be?post a message in the easycfm.com forums and let others know how much faster your queries are now! If not, don?t say anything and pretend that this never happened (kidding?post to the forums ESPECIALLY if the results don?t show a significant improvement in speed?there may be a problem elsewhere, and we?ll all do what we can to figure out the issue).

Now that you?re convinced, let?s go over the syntax. This is the easy part. <cfqueryparam> takes two attributes.

1) the value (VALUE)
2) the datatype (CFSQLTYPE)

You?ve seen an example above?here are a few more just to show how ridiculously easy it is:

SELECT *
FROM MyTable
WHERE birthday = <cfqueryparam value=?#createODBCDate(form.birthday)#? cfsqltype=?cf_sql_date?>

SELECT *
FROM MyTable
WHERE username = <cfqueryparam value=?#session.username#? cfsqltype=?cf_sql_char?>

SELECT *
FROM MyTable
WHERE hits > <cfqueryparam value=?#URL.hits#? cfsqltype=?cf_sql_integer?>

As you can see, it?s quite simple. The value is simply the value you?re searching for. Notice also that you can use CF Functions within the value attribute (I used the createODBCDate() function in the first example above).

The cfsqltype attribute values are as follows:

  • CF_SQL_BIGINT
  • CF_SQL_BIT
  • CF_SQL_CHAR
  • CF_SQL_DATE
  • CF_SQL_DECIMAL
  • CF_SQL_DOUBLE
  • CF_SQL_FLOAT
  • CF_SQL_IDSTAMP
  • CF_SQL_INTEGER
  • CF_SQL_LONGVARCHAR
  • CF_SQL_MONEY 
  • CF_SQL_MONEY4 
  • CF_SQL_NUMERIC 
  • CF_SQL_REAL 
  • CF_SQL_REFCURSOR 
  • CF_SQL_SMALLINT 
  • CF_SQL_TIME 
  • CF_SQL_TIMESTAMP 
  • CF_SQL_TINYINT 
  • CF_SQL_VARCHAR

The cfsqltype attribute is NOT required (it defaults to cf_sql_char), but highly encouraged. You?ll likely find yourself using cf_sql_char, cf_sql_date, and cf_sql_integer the most frequently. The rest should be self-explanatory.

I hope you found this tutorial to be enlightening, and clear enough that it conveyed the importance of getting into the habit of using the <cfqueryparam> tag. As always, if there are any questions whatsoever, please post to the forums.

All ColdFusion Tutorials By Author: Charlie Griefer (CJ)
  • CFSCRIPT Intro
    An introductory look at CFSCRIPT. Rules, some basic syntax, and a couple of examples of loops and conditional processing.
    Author: Charlie Griefer (CJ)
    Views: 46,873
    Posted Date: Saturday, January 18, 2003
  • ColdFusion Mad Libs - Part I
    A silly but fun time-waster that you can easily include on your Web site. You might be surprised at how addicting it can become :)
    Author: Charlie Griefer (CJ)
    Views: 27,666
    Posted Date: Thursday, May 29, 2003
  • ColdFusion Mad Libs - Part II
    You've finished the first Mad Libs tutorial, but you feel like there's something missing. Of course there is! You want to be able to save the final output to a database to let your visitors browse through other user's stories. Includes a bad-words filter for the more conservative among us :)
    Author: Charlie Griefer (CJ)
    Views: 22,838
    Posted Date: Thursday, May 29, 2003
  • to cfqueryparam or not to cfqueryparam
    It's been out there since ColdFusion 4.5...most of us have heard of it...few of us use it. Here are some compelling reasons why you should get into the habit of using the tag.
    Author: Charlie Griefer (CJ)
    Views: 34,135
    Posted Date: Thursday, May 29, 2003
  • Dynamic Column Output (Part One)
    Have you ever wanted to display your content in rows of 3 columns? If you ever wanted to specify the number of columns per row within your content, here's the tutorial for you.
    Author: Charlie Griefer (CJ)
    Views: 34,986
    Posted Date: Thursday, May 29, 2003
  • Dynamic Column Output (Part Two)
    This tutorial picks up where the Dynamic Columns tutorial left off, showing you how to not only output your data in a specified number of columns, but how to do it while still publishing well formed HTML.
    Author: Charlie Griefer (CJ)
    Views: 27,533
    Posted Date: Saturday, May 31, 2003
  • Remote File Management
    Manage text-based files on your server from any Web browser. Create a new file, edit a file, or delete a file. Can be a life saver if you're on the road, and find an error in some of your code that needs a quick fix.
    Author: Charlie Griefer (CJ)
    Views: 27,815
    Posted Date: Tuesday, June 3, 2003
  • Save your visitor's clickstreams
    A nifty little custom tag that will allow you to save a visitor's clickstream through your site, as well as display it back to them (with links). Did I really just say 'nifty'?
    Author: Charlie Griefer (CJ)
    Views: 25,608
    Posted Date: Monday, June 16, 2003
  • Grouping Output in CF
    How to group cfquery output in order to effectively display relational database data. Includes an overview of how to output nested groups as well.
    Author: Charlie Griefer (CJ)
    Views: 32,507
    Posted Date: Tuesday, June 17, 2003
  • arrays and structures - part 1
    part one of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 38,749
    Posted Date: Monday, August 11, 2003
  • arrays and structures - part 2
    part two of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 28,289
    Posted Date: Monday, August 11, 2003
  • arrays and structures - part 3
    part three of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 33,332
    Posted Date: Monday, August 11, 2003
  • JavaScript Form Validation
    Yes, I know we're a ColdFusion site...but ColdFusion does not live in a vacuum. We have to know SQL, HTML, CSS...and sometimes...JavaScript! This tutorial focuses on using JavaScript (in lieu of cfform) to create client side form validation (and explains why writing your own is better than using ).
    Author: Charlie Griefer (CJ)
    Views: 58,281
    Posted Date: Thursday, August 14, 2003
  • CF 'Best Practices'
    Some tips and techniques that I've picked up over the years. I don't maintain that these are 'official' or 'absolute'...they are simply my preference and things that have worked for me. I would like to share them here, and leave you to make the decision as to whether or not they fit in your 'code arsenal' :)
    Author: Charlie Griefer (CJ)
    Views: 35,637
    Posted Date: Friday, August 15, 2003
  • Helping users obtain their passwords
    Your site requires your visitors to log in. of course, some of your visitors are going to forget their passwords (ok, most will forget their passwords). You don't want them to have to send you an e-mail, and then wait for a response. They need immediate access.

    This tutorial shows two methods by which you can accomodate them.
    Author: Charlie Griefer (CJ)
    Views: 26,198
    Posted Date: Thursday, August 28, 2003
Download the EasyCFM.COM Browser Toolbar!