I recently had the need to control collation order on DB2/400. Essentially, I had a multi-column data grid on a web page and one of the columns contained data that was alphanumeric. The data in the data grid was ordered on this column. By default, on DB2/400, the collation order for sorting the table I was querying is determined by the hexadecimal
EBCDIC value. This caused letters to come before numbers like this:
I had a request to change the order so that numbers came before letters so that this list would instead look like this:
It turns out that with DB2/400, this was quite simple. But first, here are some search terms to help Google find this article for you.
DB2/400 Collation Order
DB2/400 Collation Algorithm
DB2/400 Sort Sequence Table
IBMDA400 Collation Order
IBMDA400 Collation Algorithm
IBMDA400 Sort Sequence Table
.NET Native Provider Collation Order
.NET Native Provider Collation Algorithm
.NET Native Provider Sort Sequence Table
iSeries Collation Order
iSeries Collation Algorithm
iSeries Sort Sequence Table
The key to solving this problem on DB2 is using a sort sequence table. It turns out that there are some already available. By default, I was getting the HEX sort sequence table. This causes the order to be determined by each character's
EBCDIC value. There are two other builtin sort sequence tables as well,
LANGIDSHR causes both the uppercase and lowercase value for each letter to have the same sort sequence (shared ->
SHR). Thus, instead of this order:
you would get this order:
or possibly even:
A have the same sort sequence value, they could come in either order.
LANGIDUNQ causes the uppercase and lowercase value for each letter to be sorted together, but still keeps their sort sequence slightly different (unique ->
UNQ), causing lowercase to come before uppercase, like this:
What is really cool about this is that you can also create your very own custom sort sequence, and you can use one of the builtin ones as the starting point. Or you can view one of the builtin ones. To do either of these activities, read this article.
Make sure you specify
*PROMPT for the Source File,
*SRTSEQ for the
Table type, and specify a Basing sort sequence of
You should be aware that the link above also shows how to create conversion tables too, like EBCDIC to ASCII, etc.
So, after discovering the link above, I had initially thought I would need to create my own custom sort sequence where I specified that numbers would come before letters. However, it turns out that
LANGIDUNQ already do that too! So all I had to do was specify one of those sort sequences. I chose to use
LANGIDUNQ because fundamentally, I like the idea of the uppercase and lowercase being ordered differently just for visual grouping so that I don't end up with this:
By the lowercase and uppercase having (slightly) different sort sequences, I would get this instead:
This is visually more appealing to me.
Now my only obstacle was to somehow specify the sort sequence table to be used. My preference would have been to be able to provide it in the SQL query itself, but I never found a way to do that. This would have allowed me to control the ordering for just this query without risking any other queries.
However, I did find how to control the sort sequence table through the connection string. And, if I wanted to control the collation order on a single SQL query, I could always use a different connection string for that query only.
For the IBMDA400 provider, use the Sort Sequence and Sort Language ID properties. You can find them documented here.
LANGIDUNQ sort sequence, I simply provide the value of 2, like this:
When you use either the
LANGIDSHR sort sequence with
IBMDA400, you must also specify the Sort Language ID property. For me, it is English, which is
ENU, like this:
Sort Language ID=ENU;
So my connection string for
IBMDA400 looks like this:
Provider=IBMDA400; Data Source=<server>; User ID=<user>;
Password=<password>; Force Translate=37; Sort Sequence=2; Sort Language ID=ENU;
Of course, I have the appropriate server, user, and password specified.
.NET DB2 Native Provider (iDB2Connection)
You can also specify the sort sequence when using the .NET native provider. For the .NET native provider, you specify the
SortLanguageId properties. Notice these don't have spaces in them, unlike the
IBMDA400 provider properties. Here is what that portion of your connection string should look like:
You can read all about the .NET native provider properties in this excellent document here.
Just so you are aware, I haven't tested this with the .NET native provider which is why I am also not providing the full connection string. I have however verified the
IBMDA400 connection string properties.
As a .NET developer, I must say that I am impressed with how simple IBM has made controlling the collation order. This turned out to be quite simple to do and is a nice trick to have in your bag.