Because the column is a character column the numbers are going to be ordered by a binary sort. You want to order them numerically, which means you need 2 ORDER BY clauses
- A numeric, where only numeric characters are considered
- A standard binary sort
select column_name
from table
order by case when regexp_like(column_name, '^\d+$') then to_number(column_name) end
, column_name
The regular expression is
^
- anchor to the beginning of the string
\d
- match only numbers
+
- match the previous expression any number of times
$
- anchor to the end of the string
It serves to enforce that only numbers exist prior to converting the column to a number for the initial sort.
More generally, it's never wise to put numbers and characters in the same column, for the reason that you've discovered and because it prevents you from enforcing that the data type is correct.
Lastly, consider whether you actually need to order your query at all, sorting is usually only necessary for display purposes or for applying some business logic to the "top" N elements of a sorted data set.