Obtaining Affected rows from SQL Query

In ColdFusion, it is easy to get the row count from a SQL select statement, just use recordcount. But what about when you do an insert, update or delete? In these cases recordcount is always 0, and a cfdump or using getMetaData doesn't help either. On CF-Talk Qasim Rasheed posted a way to get the amount of affected rows using Java and the JDBC drivers. I'm going to split this in two, because the first part is database specific. For Oracle, use this:

<cfscript>
//connection url
connURL = "jdbc:macromedia:oracle://..........";
jclass = createobject('java','java.lang.Class');
jclass.forName('macromedia.jdbc.oracle.OracleDriver');

For Microsoft SQL Server:

<cfscript>
//connection url
connURL = "jdbc:macromedia:sqlserver://<server name>:1433";
jclass = createobject('java','java.lang.Class');
jclass.forName('macromedia.jdbc.sqlserver.SQLServerDriver');

The last part of the code is the same for any database:

driverManager = CreateObject('java', 'java.sql.DriverManager');
//user name and password
conn = driverManager.getConnection( connURL, 'USER', 'PASSWORD' );
sql = "update budgets.dbo.budgetids set CC = ? where budgetid like ?";
ps = conn.prepareStatement(sql);
ps.setString(1,'400');
ps.setString(2,'B007%');
n = ps.executeUpdate();
</cfscript>
<cfoutput>
Records Affected: #n#
</cfoutput>

You can see that we are using prepared statements here. Any place that you pass in a value, use a question mark. Then use the setString function to populate those values with your data.

Comments
for ms sql server, you're working way too hard:

<cfquery name="updateSomething" datasource="someMSSQLSERVERdsn">
   SET NOCOUNT ON
      UPDATE authors
         SET au_lname = 'Jones'
      WHERE au_id = '999-888-7777'
      
      SELECT rowsEffected=@@ROWCOUNT   
   SET NOCOUNT OFF
</cfquery>

<cfoutput>
rows updated:=#updateSomething.rowsEffected#
</cfoutput>
# Posted By PaulH | 4/21/06 2:11 AM
Yeah, good point Paul. The reason I don't like that solution is because it doesn't work in most other DBMSes (they don't allow more than one query). Since this is a security issue, I'm hoping that eventually Microsoft will catch up with the rest of the DB world, and when/if that happens your suggestion will no longer work.
# Posted By yacoubean | 4/21/06 8:04 AM
then how do you write sp in oracle or other dbms? what you're saying doesn't make sense to me.

there's really nothng wrong w/multiple SQL statements, you can not write useful sp w/out then. and if your code is susceptible to sql injection you're screwed no matter what.

as far as sql server dropping it, kind of doubtful.
# Posted By PaulH | 4/21/06 8:11 AM
Security issue? huh?
# Posted By Darin Kadrioski | 4/21/06 10:47 AM
Man, I've had this conversation with so many MS SQL Server guys lately. :)

SQL injection is the problem, and it's only a problem when you are running queries from an outside source. SPs are run locally by a developer, so Oracle and DB2 allow that. But if you are making a connection from another source (like from a web server), Oracle and DB2 silently ignore any extra queries you send them (they probably do allow you to execute an SP with multiple queries, however). We have DB2 and Oracle servers here at work, I have tried to run multiple queries from my SQL Servers (using OpenQuery), and they won't allow it.
# Posted By yacoubean | 4/21/06 12:53 PM
Oh, well yeah. SQL injection is *always* a problem. Assuming you are using cfqueryparam (as everyone should already be doing by now) then I don't see any security concern with executing multiple statements in one query. Certainly wouldn't blame MS for allowing that action, if I was naive enough not to use cfqueryparam and was compromised.
# Posted By Darin Kadrioski | 4/21/06 1:40 PM
Well, it's just more of the same from Microsoft. In Linux/Unix/Mac OS you have to turn potentially insecure features on if you want them, because they are off by default. The same with Oracle/DB2/MySQL. Microsoft prefers to leave potentially insecure features on and leave it up to the user/developer to secure it themselves. That is why Microsoft has such a bad security track record.
# Posted By yacoubean | 4/21/06 9:57 PM
There is a DB non specific way of getting a connection, without having to worry about which DB you are using -

dss = createObject("Java", "coldfusion.server.ServiceFactory").getDataSourceService()

conn = ds.getDatasource("dbname").getConnection();

ps = conn.prepareStatement("...");

and on from there.

One thing you must note - do call conn.close() when you are done with your connection.

I've noticed with some DB's and CF, they may not neccessarily release the connection, even if you aren't using it anymore, particularly for external JDBC drivers like mySQL 4.x+.

Of course.. all this stuff is non supported etc etc etc

Enjoy.
# Posted By Mark Mandel | 5/1/06 1:37 AM
The use of the service factory is the best option (because in CF we always use pre-confitured datasources). And makes everything simplier.

<cfscript>
   dss = createObject("Java", "coldfusion.server.ServiceFactory").getDataSourceService()
   conn = dss.getDatasource(arguments.datasource).getConnection();
   sql = "update mytable
      set mycolumn = #cfmyownvariable#
      where col2 = #othervariable#;
   ps = conn.prepareStatement(sql);
   affectedRows = ps.executeUpdate();
</cfscript>

Very simple, very helpfull.
# Posted By Nestor Mata | 3/9/07 1:50 PM
Aside from the fact that the service factory is unsupported, undocumented, and may very well change and/or go away in future versions of CF. But if you're happy to live with that, go for it. :)
# Posted By Jake Munson | 3/9/07 1:58 PM
Yes, you may be right about that, but that could be worked arround by adding this into a custom tag and then if the service gets changed you can modify to use it, because anyway the core of the code is just standard java and there will definiltly will always be a way to obtain the datasource and if it get to change we could talk to Adobe's support or any guru to find the new way. ;)
So, if you are not a java developer you may decide to keep away from this solution or not, but I would say that if you have some java knowlege I'm pretty sure you can just jump ahead and you will have a way to fix it if Adobe decides to make a change there.
There is always a little risk when mixing languages, but all depends on the pros and cons to see if the benefit worth it and is always up to each developer.

And always remember that there is a big comunity willing to answer and helping each other.
;)

Nestor
# Posted By Nestor Mata | 3/12/07 10:41 AM
thanks all of you! interesting and helpful stuff.
# Posted By Sadara | 7/5/07 11:26 PM
I'll second to that. Very helpful. Been searching for this for a while now.
# Posted By William from Lagos | 7/21/07 3:14 PM
I'll second to that. Very helpful. Been searching for this for a while now.
# Posted By William from Lagos | 7/21/07 3:16 PM
Can u help me to get the Affected rows from SQL Query in Coldfusion version 7
# Posted By puviarasi | 4/16/08 10:19 PM
How about to try SQL%ROWCOUNT keyword?

http://www.java2s.com/Code/Oracle/PL-SQL/Implicitc...

Jeff
# Posted By Jeff | 8/12/08 12:13 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9. Contact Blog Owner