Most people know that you should always use cfqueryparam on your query parameters when querying a database to (among other things):
- secure your database from unauthorised/malicious users
- perform data validation
- take advantage of SQL bind parameters
The cfqueryparam tag can and should be used whether the query be a SELECT, UPDATE, DELETE or INSERT.
One of the problems I’ve had in the past is when I want to either INSERT or UPDATE a column which has an INT datatype (MSSQL), but that column is not mandatory and therefore allows NULL values. Traditionally (if not using a stored procedure) I would have an approach as follows:
<cfquery name="qAddUser" datasource="#application.dsn#"> INSERT INTO MyUsers ( Age, FirstName, LastName ) VALUES ( <cfqueryparam cfsqltype="cf_sql_integer" value="#trim(form.iAge)#" maxlength="3" />, <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.sFirstName)#" maxlength="50" />, <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.sLastName)#" maxlength="50" /> ) </cfquery>
This works nicely except remember that ‘Age’ isn’t a mandatory column in the database, so if the user leaves that form field blank I’ll be passing through an empty string (form.iAge) to the cfqueryparam. Because the database is expecting an INT value it really won’t like my empty string so I’ll get a nice big error. Now to get around this I have a couple of immediate options.
- use a database default (e.g. 0)
- Use conditional logic to set the empty string to an INT, like 0
- Use conditional logic to use the NULL attribute of cfqueryparam
Number 3 is my preferred option, I don’t want the value ‘0′ in the database when I don’t know if it’s really a valid value. Did the user type in ‘0′ or is it my default database value? Sure I could use something like ‘-1′ instead or code my application to know that if a ‘0′ (or ‘-1′) was found then I know that it’s actually a NULL value. But that just seems messy to me.
The NULL attribute of cfqueryparam can take a value of ‘yes|true’ or ‘no|false’ and if set to ‘yes|true’ then anything in the ‘value’ attribute is ignored and a NULL is passed to the database. This is what we want! Unfortunately though if I do use null=”yes” and I also have a ‘value’, then that value will be ignored and NULL will be used instead. To get around this I need to do something like:
<cfif NOT len(trim(form.iAge))> <cfqueryparam cfsqltype="cf_sql_integer" value="#trim(form.iAge)#" maxlength="3" null="yes" /> <cfelse> <cfqueryparam cfsqltype="cf_sql_integer" value="#trim(form.iAge)#" maxlength="3" /> </cfif>
That would work but it’s not really that neat or optimal (in terms of coding and reading).
As usual it’s always the simple solutions which are right in front of you that work the best! Today I saw a nice solution to this all too common problem from Ian Skinner over on Google groups where Ian used the yesNoFormat() and len() functions to conditionally pass in null or a value like:
<cfqueryparam cfsqltype="cf_sql_integer" value="#trim(form.iAge)#" maxlength="3" null="#yesNoFormat(NOT len(trim(form.iAge)))#" />
This is nice an simple, the len() function will return the length of the string (0 or more) and the yesNoFormat() will translate that into the boolean value we need for the NULL attribute.
However because we want to use the NULL attribute if the string DOESN’T have a length…we use the NOT boolean operator to reverse the results.
Note that because we are using NOT, our result will be the desired boolean therefore negating the need to use yesNoFormat(). That leaves us with:
<cfqueryparam cfsqltype=”cf_sql_integer” value=”#trim(form.iAge)#” maxlength=”3″ null=”#NOT len(trim(form.iAge))#” />
Nice and clean

11 Comments
That is nice approach to using the null – quite cool! One other approach to handling this for integers is to RegEx your string to remove all non-numerics.
If you really think it through, the benefits of cfqueryparam are primarily for strings as it stops you having to try to parse a string to remove any possible variant of delete table (or whatever injection required). For bits, dates, integers, floats and the like, a simple regex transformation and/or validation in your code is (to my mind) simpler.
Just my 2c!
Nice explanation Michael. I’ve been using the YesNoFormat trick for a while but the double negatives have always bothered me. For strings (and as Peter says it’s normally strings) I’ve recently started using a simple “isEmptyString” UDF to make my cfqueryparams more readable.
I tend to use
, which I think compiles to the same thing on the backend. I ran some fairly extensive speed comparison tests between eq “” and not(len()) a while back and came up with the same numbers, though that was on CFMX 6.1, things may have changed in 7
I tend to use
<cfqueryparam ….. null=”#trim(iFormElement) eq ”#”>, which I think compiles to the same thing on the backend. I ran some fairly extensive speed comparison tests between eq “” and not(len()) a while back and came up with the same numbers, though that was on CFMX 6.1, things may have changed in 7
Note that (at least with CF8), there’s no need for using YesNoFormat() — like all other CF tag attributes that expect a boolean value, all the usual CF booleans will suffice (0/1, no/yes, true/false). So a simple …null=”#NOT structKeyExists(arguments, ‘age’)#”… will do the trick. I would expect this to be true of all CF versions, but only have CF8 ready to hand.
@Tracy – Yep, the last example in the post details that.
There was a problem with the syntax highlighter I was using so I don’t think it was displaying correctly.
I’ve removed the highlighter for the last example and just left it bold.
Thanks
Will this work for a varchar field also? I tried using your example and just replaced your field name and the data type and it’s not working.
Thanks,
Eric
You also need to mention that this is not for radio boxes. Spent a good deal of time finding this out the hard way.
Thanks,
Eric
@Eric – This would indeed work for varchars, not sure what went wrong for you. Do you have a code sample?
For radio buttons you could replace len(trim()) with isDefined(“myRadioButton”)
Hope that helps.
I ran into same situation and found this post. Thanks a million this was exactly what I was looking for.
cheer!
so this is the best way for all datatypes?
null=”#NOT structKeyExists(arguments, ‘age’)#