Oracle permite ordenar texto según las reglas lingüísticas de cada idioma.

Hay que tener en cuenta que cada alfabetización es diferente.

Por ejemplo, en noruego hay tres caracteres que no existen en el alfabeto europeo tradicional. En su abecedario, estas tres letras van al final y por ese orden: Æ, Ø, Å

En el catalán y español, la Ç y la Ñ se situan justo detrás de la C y la N.

Pero, aunque sean muy similares, en catalán la CH no existe como letra, por lo tanto, en español o en catalán deberán tener diferentes posiciones.

SQL> select c1 nombre
  2	 from (values
  3	 ('Maa'), ('Mab'), ('Maca'), ('Maco'), ('Macu'), ('Mach'), ('Mad')
  4	 )
  5	 t ( c1 )
  6	order by c1 collate spanish;

NOMBRE
----------
Maa
Mab
Maca
Maco
Macu
Mach   -- La CH va detrás de C en español
Mad

7 rows selected.

SQL> select c1 nombre
  2	 from (values
  3	 ('Maa'), ('Mab'), ('Maca'), ('Maco'), ('Macu'), ('Mach'), ('Mad')
  4	 )
  5	 t ( c1 )
  6	order by c1 collate catalan;

NOMBRE
----------
Maa
Mab
Maca
Mach   -- La CH no se considera letra del alfabeto y se ordena entre G e I.
Maco
Macu
Mad

7 rows selected.

No sólo eso, sino que Oracle permite que esas ordenaciones sean transparentes a mayúsculas y acentos, basándose en cómo se posicionan éstas en el alfabeto.

Dicho esto, no es necesario utilizar funciones de conversión de carácteres como UPPER(), LOWER(), TRANSLATE() o REPLACE() para tener un conjunto de filas ordenadas según español, catalán o inglés.

Vamos con un ejemplo.

Supongamos esta lista de valores, que incluye mayúsculas, minúsculas, letras con tilde (abiertas y cerradas), ce con cedilla (ç) y eñes (ñ):

‘Maçia’, ‘Mañia’, ‘Mabia’, ‘Macia’, ‘Mania’, ‘MAria’, ‘Maria’, ‘MÁria’, ‘MÉria’, ‘MÍria’, ‘MÓria’, ‘MÚria’, ‘maria’, ‘mária’, ‘méria’, ‘míria’, ‘mória’, ‘múria’, ‘Maxia’, ‘MEria’, ‘Meria’, ‘meria’, ‘MIria’, ‘Miria’, ‘miria’, ‘MOria’, ‘Moria’, ‘moria’, ‘MUria’, ‘Muria’, ‘muria’

Ordenar con LOWER(nombre) no va a funcionar bien. Tampoco sirve utilizar REGEXP o funciones por el estilo.

No hace falta.

En el siguiente ejemplo, sin siquiera necesidad de usar una tabla física, generamos una tabla dinámica a partir de la lista de valores. Con COLLATE y el sistema de ordenación SPANISH_AI indicaremos que queremos una ordenación en base a las reglas de español sin sensibilidad a considerar acentos, mayúsculas o minúsculas.

select c1 nombre
 from (values 
    ('Maçia'), ('Mañia'), ('Mabia'), ('Macia'), ('Mania'), ('MAria'), ('Maria'),
    ('MÁria'), ('MÉria'), ('MÍria'), ('MÓria'), ('MÚria'), ('maria'), ('mária'),
    ('méria'), ('míria'), ('mória'), ('múria'), ('Maxia'), ('MEria'), ('Meria'),
    ('meria'), ('MIria'), ('Miria'), ('miria'), ('MOria'), ('Moria'), ('moria'),
    ('MUria'), ('Muria'), ('muria')
    )    t ( c1 ) 
order by c1 collate spanish_ai;
	
NOMBRE
----------
Mabia
Maçia   -- La ubicación correcta de Ç es entre B y C.
Macia
Mania
Mañia   -- La ubicación correcta de Ñ justo después de N.
Maria
MAria
Mária   -- A, a, Á, á, se consideran al mismo nivel
mária
maria
Maxia
meria
Meria
méria
MÉria
MEria
MÍria
míria
miria
Miria
MIria
MÓria
moria
MOria
mória
Moria
muria
MÚria
múria
Muria
MUria

31 rows selected.

¿Qué hacer cuando necesitamos una ordenación específica?

Si necesitas ordenar por un criterio que no sea ortográfico o lingüístico, debes usar una columna numerada para el orden/posición de esa fila respecto al resto. La típica fila SORT_NUMBER o similar para tener por número una ordenación arbitraria.

Si quieres que un carácter de se ordene una forma especial, mi recomendación es que crees una ordenación específica o modifiques una de las estándares para el idioma que desees.

Para ello tienes la utilidad Oracle Locale Builder.

[oracle@localhost ~]$ lbuilder

Esta utilidad te permite cargar los ficheros de definiciones locales, y te permite establecer cómo quieres que se comporte según el lenguaje, territorio, juego de carácteres y ordenación lingüística.

Por ejemplo, voy a crear una ordenación personalizada del español llamada SPANISH_AMI por ser «a mi modo». En ella quiero que los números cero y tres se ordenen junto a la letra O y la E.

Esto se consigue modificando la “ordenación principal” y la “ordenación secundaria” para que se ubiquen en la posición deseada.

Guardo los cambios en el directorio de NLS por defecto de Oracle, que es $ORACLE_HOME/nls/data , y las ordenaciones ahora pueden acceder a esta nueva ordenación a través de los nuevos ficheros creados con las reglas que hemos personalizado.

Y ahora, cuando en la cláusula ORDER BY indico que quiero que se ordene bajo mi personalización de ordenación de español “A mi manera”, el número 3 se ordena junto a la letra E, y el cero junto a la letra O.

SQL> select c1 nombre
2 from (values
3 ('Maa'), ('Mae'), ('Mai'), ('Mao'), ('Mau'), ('Ma0'), ('Ma1'),
4 ('Ma2'), ('Ma3'), ('Ma4'), ('Ma5') )
5 t ( c1 )
6 order by c1 collate spanish_ami;

NOM
---
Maa
Mae
Ma3 --> El 3 se alínea ordenado con la letra E
Mai
Mao
Ma0 --> El 0 se alínea ordenado con la letra O
Mau
Ma1
Ma2
Ma4
Ma5

11 rows selected.
Share This