lunes 9 de julio de 2007

Cuestiones de idioma

Muchas veces necesitamos comparar días de la semana con SQL y usamos funciones como to_char, to_date, next_day, y otras. Con ellas podemos obtener el número de día de la semana o el nombre del día o del mes, y usarlo para evaluar alguna condición.
En estos casos deberíamos preguntarnos si nuestro código depende del idioma en que esté configurado el cliente o la base de datos. Si esto es así, estamos haciendo que nuestras aplicaciones sean dependientes del lugar donde se instalen y eso no es deseable.

Recordando que el orden de preferencia para los seteos del NLS es (de mayor a menor):

1) NLS explicitado en función
2) NLS configurado en la sesión del usuario
3) NLS configurado en el cliente
4) NLS configurado en la base de datos

...es una buena práctica 'asegurar' el idioma o territorio a utilizar cuando usamos una función que depende de eso.
Yo prefiero que mis aplicaciones dependan lo menos posible de una configuración especial en el cliente o la base de datos, por lo tanto siempre voy a intentar aplicar 1) o 2).

Ejemplo 1: Días de la semana como palabra

Obtener las marcas de los empleados los dias sábados:

SELECT timestamp, employee
FROM timer_tbl
WHERE to_char(timestamp,'DAY') = 'SATURDAY';

En este caso la consulta depende del idioma que este configurado en la sesion o en el cliente o la base de datos, y rezaría para que siempre fuera ingles!
Para evitar ese tipo de ataduras de infraestructura, puedo pasarle a to_char el parametro NLS_DATE_LANGUAGE y entonces estoy en el caso 1) de máxima prioridad.
Me quedaría:

SELECT timestamp, employee
FROM timer_tbl
WHERE to_char(timestamp,'DAY','NLS_DATE_LANGUAGE=AMERICAN') = 'SATURDAY';

Ejemplo 2: Número de día de la semana

En algunos territorios como Portugal y USA el primer día de la semana es el domingo, en otros como España y América del Sur es el lunes. Esto hace que la máscara 'D' de to_char sea diferente según el territorio.
El número de dia de la semana depende del parametro NLS_TERRITORY, pero no lo puedo pasar como tercer parámetro, no es válido.

En ese caso tendré que alterar la sesión para asegurar que el día 1 sea el lunes para mi aplicación.

SQL> alter session set nls_territory='AMERICA';

Session altered.

SQL> select to_char(sysdate,'D DAY') HOY from dual;

HOY
-----------------------------
1 MONDAY

Ver tambien
Acentos del idioma español