Saturday, April 21, 2007

Be prepared for Oracle-Prepared Statements

I am a starter with Oracle databases and hence this article might be very obvious to people who are working with databases since 4-6 months or more. When I faced this problem, I googled a lot but could not find much about it and hence decided to put this up in blog.

It all started when I had to delete few rows from my database table. Table had two columns:
name -> varchar(20);
id -> char(5);

I was testing my program of deleting rows and hence, before deleting rows, I was inserting few in table.
I inserted following three rows
a 1
b 2
c 3
and started deleting rows with following code:

DEL_SQL = "delete from table_name where id = ?"
PreparedStatement del = conn.prepareStatement(DEL_SQL);
for(int i=0; i<3;>
del.setString(1, Integer.toString(i));
int updated = del.executeQuery();
System.out.println("Number of rows affected: " + updated);
}

I ran this program and surprisingly, value of "updated" was always 0. Went everywhere to look for mistake I have made.. from Connection to PreparedStatement, from Integer to String.. but could not find any mistake there.
After I toiled for one day, next day I just thought of looking for the difference between varchar(n) and char(n) and came to know that "char(n) is a fixed length string of n characters. So if you put a string of length n-m, this string will be padded by m space/blank characters".

It means that when I inserted values "1", "2", and "3" in "id" column, it was padded by extra spaces. :(
i.e. value in database table of id was "1 ", "2 " and "3 " and hence when I was trying to delete such rows, result of equality I was looking for was false.

"trunc()" function, provided by Oracle came to my rescue and I modified by DEL_SQL to:
"delete from table_name where trunc(id) = ?"
and it started working fine.

Unfortunately, this problem doesn't occur when you use such queries from command line (SQLPlus).
My suggestion is to take special care while querying columns of fixed length datatype like "char(n)".

Please let me know if my conclusion is wrong or if there is some better way of handling this scenario.

Thanks for taking time to read this.