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 aplicar 1) o 2).

Ejemplo 1: Días de la semana como palabra

Obtener las marcas de los empleados los días 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 sesión o en el cliente o la base de datos, y rezaría para que siempre fuera inglés!
Para evitar ese tipo de ligaduras con la región, puedo pasarle a to_char el parámetro 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 parámetro 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 también:
Acentos del idioma español

7 comentarios:

Anónimo dijo...

hoy es 23/06/2008
Estoy en Argentina.
Si se ejecuta la siguiente consutla en el PL/SQL DE ORACLE

select to_char(sysdate,'ww') semana
from dual

Deberia traerme la semana actual.
El echo es que me trae como resultado 25, sin embargo la semana acutal es 26
Intente hacer alter session set nls_territory='SPAIN';
como dice el blog que muy interesante esta por cierto, pero arroja el mismo resultado.
Alguna sugerencia?
P/D: cuando es martes el mismo QRY me arroja como resultado 26, como deberia ser.

Anónimo dijo...

Echa la pregunta formal, encontre la respuesta a mi propia consulta.
Si se utiliza select to_char(sysdate,'ww')semana
from dual
se obtendra la semana correspondiente al primer dia de la semana de cada region.
En EEUU comienzan con el dia Domingo la semana en cambio en Argentina y en America comenzamos la semana con el dia Lunes.
Por eso nunca va a dar el primer dia el mismo numero.
Existe en PL/SQL reemplazar el WW por IW que es un ISO PARA LA SEMANA Standard.
Si se utiliza select to_char(sysdate,'iw')semana
from dual
obtendremos que el dia de la semana de hoy es 26
el_luyi

Anónimo dijo...

buenas compañeros BDa mi consulta en que debo elaborar un reporte en el cual me seccione el año en semanas cada semana con su fecha de inicio y su fecha de de finalizado le s escribo desde Panama

lfer dijo...

Ya que estas elaborando este tipo de reportes, una practica comunmente utilizada es crear una tabla Calendario, con una columna dia (date), otra numero de la semana (number), otra numero de mes (number), numero de cuatrimestre (number), etc.
Luego para este caso puedes agrupar por numero de semana, y obtener el minimo y maximo dia. Joineas con tus tablas de datos que deseas proyectar y listo. Todo con SQL.

Saludos

Anónimo dijo...
Este comentario ha sido eliminado por un administrador del blog.
lfer dijo...

Algunos comentarios relacionados con vistas parametrizadas fueron movidos para aquí.

Anónimo dijo...

por que nadie sabe hacer una condicion con timestamp de todos los registros entre las 6 y 7 de la mañana?????