If you want to convert decimal (base 10) to to hexadecimal (base 16) in SQL you can do so easily with the built in `to_char`

functionality:

1 | select trim(to_char(300, 'XXXXX')) dec2hex |

What if you wanted to convert a decimal number to base 20 or any other base? This question recently came up when I was looking to add a transactional number generator for OOS Utils. The goal of the ticket is to convert a sequence number into a human readable number (ex: invoice number). It can easily be solved using PL/SQL (solution below) but I wanted to see if I could do it in SQL as it presents an interesting problem.

## The Formula

For some, this section will go down memory lane to your college / university years where you had to convert dec to hex by hand. It’s important to understand the formula to convert dec to hex (or any base),

Using the first example, this is how to convert `300`

to `12C`

“by hand”: *Note Q = Quotient, R = Remainder*

`300/16 = Q: 18, R: 12 (hex: C)`

`18/16 = Q:1, R: 2 (hex: 2)`

`1/16 = Q: 0, R: 1 (hex: 1)`

The steps above produce the hexadecimal number `12C`

. More importantly, each value is dependent on the calculation of the previous line. This isn’t easy to do in SQL.

## PL/SQL Function

The following function will convert dec to hex in PL/SQL:

1 | create or replace function dec2hex ( |

As you can see PL/SQL uses the quotient from the previous loop to calculate the current loop’s remainder.

## SQL Solution

In SQL, finding the value of the previous row is easy using an analytic function such as `lag`

. If you’ve never used analytic functions before, Connor McDonald has a great series on youtube about them.

Using the previous row’s calculated value for the current row is more difficult and can’t be done using analytic functions. This is where the model clause comes in. It’s one of the lesser known features in Oracle SQL but very powerful in the right circumstances.

The query below will do dec to hex (or any other “base X”) conversion. For demo purposes I have left the `select ... from my_data`

portion uncommented to highlight the model clause. To do a full translation uncomment the last few lines.

1 | var x number; |

## Final Thoughts

The model clause is extremely powerful when used to solve problems it was intended for. The toughest thing to do is learn and understand how it works with all it’s options/function. If it’s any help, I’m still learning more about the model clause and by no means an expert.

If you do some interesting things with a model clause please blog about it and send me a message as I can list future posts in this article.