Aviso:
El que aún no haya ecuchado mil veces el ‘Grace‘ de Jeff Buckley, tiene muy serias lagunas culturales.
Saludos.
Carlos.
Aviso:
El que aún no haya ecuchado mil veces el ‘Grace‘ de Jeff Buckley, tiene muy serias lagunas culturales.
Saludos.
Carlos.
El cálculo de un factorial se suele poner como ejemplo de utilización de función recursiva. Oracle no tiene esa función (al menos por ahora) dentro de sus funciones ‘built in’ (incorporadas).
Es fácil compilar una función que acepte un parámetro numérico y devuelva su factorial. Basta con iterar un decremento de uno sobre el parámetro de entrada e ir multiplicando mientras el parámetro decrementado sea mayor que cero.
Pero ¿podría hacerse en PURO SQL, sin necesidad de recurrir a compilar la función de marras?
En eso estaba yo pensando y no sabía muy bien cómo afrontar el problema, hasta que me acordé de mis años mozos y de un profesor de matemáticas diciéndome que ‘los logaritmos convierten productos en sumas’ ( ln(a*b) = ln(a)+ln(b) ). También me acordé de otro que me decía que los ‘logaritmos y las exponenciales son funciones inversas’. Y así pensando pensando se me ocurrió esto:
carlos@db01.xxxxxx> set verify off carlos@db01.xxxxxx> SELECT EXP( SUM(LN(level))) FACTORIAL 2 FROM DUAL CONNECT BY LEVEL <= &numero
/
Introduzca un valor para numero: 3
FACTORIAL
----------
6
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 4
FACTORIAL
----------
24
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 5
FACTORIAL
----------
120
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 6
FACTORIAL
----------
720
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 7
FACTORIAL
----------
5040
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 8
FACTORIAL
----------
40320
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 9
FACTORIAL
----------
362880
carlos@db01.xxxxxx> /
Introduzca un valor para numero: 10
FACTORIAL
----------
3628800
carlos@db01.xxxxxx>
Otra prueba más de que hay muy pocas cosas que no se puedan hacer con simple SQL.
Saludos.
Carlos.
Muchas veces trabajamos asumiendo comportamientos ‘intuitivos’ al funcionamiento funciones o procedimientos estándar. (Es lógico: si no fuera así, deberíamos estudiar exhaustivamente toda la documentación y de nada nos valdría cualquier tipo de ‘background’ obtenido con años y años de experiencia de uso de un determinado ’software’ o de otros parecidos).
Así pues, muchas veces asumimos que cierto subprograma funcionará así ‘porque es lógico’.
Pero eso puede no ser cierto: Por ejemplo, TO_DATE() tiene un comportamiento un poco peculiar a la hora de decidir dónde truncar a partir del formato que se introduzca:
Si el formato llega hasta día, trunca a día (es decir, establece las 00:00:00):
carlos@db01.xxxxxx> select TO_DATE('01012007','DDMMYYYY') from dual;
TO_DATE('01012007',
-------------------
01/01/2007 00:00:00
Si el formato llega hasta mes, trunca al primer día del mes (a las 00:00:00):
carlos@db01.xxxxxx> select TO_DATE('012007','MMYYYY') from dual;
TO_DATE('012007','M
-------------------
01/01/2007 00:00:00
Pero si el formato llega sólo hasta el año: trunca al primer día del mes ACTUAL (esto es lo ‘contraintuitivo’: no truncar al primer día del año):
carlos@db01.xxxxxx> select sysdate, TO_DATE('2006','YYYY') from dual;
SYSDATE TO_DATE('2006','YYY
------------------- -------------------
17/07/2007 13:11:24 01/07/2006 00:00:00
En realidad hace eso cada vez que al formato le falta el mes:
carlos@db01.xxxxxx> select SYSDATE, TO_DATE('032007','DDYYYY') from dual;
SYSDATE TO_DATE('032007','D
------------------- -------------------
17/07/2007 13:12:53 03/07/2007 00:00:00
…o el año (si bien esto quizá es un poco más intuitivo: truncar al año actual)
carlos@db01.xxxxxx> select SYSDATE, TO_DATE('0320','MMDD') from dual;
SYSDATE TO_DATE('0320','MMD
------------------- -------------------
17/07/2007 13:15:43 20/03/2007 00:00:00
carlos@db01.xxxxxx> select SYSDATE, TO_DATE('20','DD') from dual;
SYSDATE TO_DATE('20','DD')
------------------- -------------------
17/07/2007 13:27:38 20/07/2007 00:00:00
carlos@db01.xxxxxx> select sysdate, to_date('11:00:00','hh24:mi:ss')
2 from dual;
SYSDATE TO_DATE('11:00:00',
------------------- -------------------
17/07/2007 13:31:12 01/07/2007 11:00:00
Ojo con esto, ya que podemos obtener resultados no esperados.
Saludos.
Carlos.
El otro día le compre sus primeras zapatillas ‘de correr’ al Bicho Nº1. Quería correr como su papi.
Las ‘zapas’: unas Adidas Vanquish del nº28.
Él está acostumbrado a ver ‘zapas de correr’ por casa:
El caso es que la cosa me ha hecho pensar en que podría casi recordar cada modelo de zapatillas que he tenido.
Creo que la afición a correr ‘en serio’ empezó con unas Adidas TRX azules y amarillas, que ‘murieron’ años después cuando mi hermano las utilizó en un partido de fútbol. Luego tuve unas estupendas Le Coq Sportif azules (no recuerdo el nombre del modelo) a las que hice más kilómetros que algunos coches. Tras éstas, recuerdo una época en las que me fundí un par de Reebok, otro par de Adidas y unas Karhu (tampoco recuerdo los nombres de los modelos). Luego vino la ‘época Nike’: unas ‘Cross Training’, unas ‘Air Pegasus’ buenísimas que cosí y recosí de lo estropedas que quedaron y, más tarde, unas ‘Air Icarus’ (mi primer maratón). Después de éstas, y a resultas de todo aquél lío de la explotación infantil y demás, volví a Adidas: las estupendas ‘Lexicon’ (que aparecen en la parte de atrás de la foto) que aún guardo, aunque están machacadas del todo.
Vino luego una temporada en la que dejé de ser un loco del ‘running’… pero el gusanillo volvió. Las Adidas Supernova azules que salen en la foto fueron mi vuelta a los maratones. Y luego las Trediac impermeables (tres vueltas al Circuito del Jarama sobre la nieve) y las Supernova blancas.
Más tarde compré las Reebok Premier Road Lite amarillas de la foto, con las que he hecho algún otro maratón y media maratón, y que todavía uso.
Y finalmente la época Asics: probé las Gel 1100 de la foto y quedé encantado. Las destrocé a base de kilómetros y me tuve que comprar otras: las Gel 2110 que aparecen en primer plano.
En una parte de la novela ‘High Fidelity’ (-también película-), el protagonista dice que podría recordar los fragmentos de su vida basándose en la música que escuchaba en cada uno de ellos. A mí casi me pasa lo mismo con las zapatillas que he ido destrozando con el paso de los años a base de hacer kilómetros corriendo (y cantando: porque cuando corro, voy cantando dentro de mi cabeza).
Saludos.
Carlos.
Ayer dejé corriendo una creación de índices en una instancia Oracle 10.2.0.1 recién instalada en un Windows 2003 Server… Al llegar esta mañana, veo que en la última línea de la ventana del SQL*plus aparece el mensaje ‘índice creado’. ‘Todo OK’, pienso. Pero cuando empiezo con la primera ‘SELECT’ me encuentro con el ORA-03113.
La Instancia está caída y no se levanta. El ‘alert log’ está lleno de
ORA-00600: codigo de error interno, argumentos: [kghstack_free2]
y de
ORA-07445: se ha encontrado una excepcion: volcado de memoria [ACCESS_VIOLATION] [_kghstack_err+104] [PC:0x603CC782] [ADDR:0xFFFFFFF0] [UNABLE_TO_READ] []
La instancia se puede montar, pero cada vez que intenta abrir la base de datos… ¡BAM!.
Miro los controlfiles y hay DOS iguales y UNO distinto! Mal rollito. Copio uno bueno (de los que son iguales) sobre el malo (el distinto). La instancia sigue sin poder abrir la base de datos.
Siguiente paso: DBVerify. Me canta errores en tres ficheros de un tablespace de datos y en un fichero de un tablespace de índices (datafiles 5,6,7 y 8).
¿Qué hacer? La base de datos era nueva, recién instalada para desarrollo y (¡snif!) en NOARCHIVELOG. No hay backup, no hay export…
Consigo que por fin abra la base de datos a base de ALTER DATABASE DATAFILE … OFFLINE DROP
Y luego :
carlos@db01.xxxxxx> recover automatic datafile 5; Recuperación del medio físico terminada. carlos@db01.xxxxxx> recover automatic datafile 6; Recuperación del medio físico terminada. carlos@db01.xxxxxx> recover automatic datafile 7; Recuperación del medio físico terminada. carlos@db01.xxxxxx> recover automatic datafile 8; Recuperación del medio físico terminada. carlos@db01.xxxxxx> alter database datafile 5 ONLINE; Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 6 ONLINE; Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 7 ONLINE; Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 8 ONLINE; Base de datos modificada. carlos@db01.xxxxxx> alter database open; Base de datos modificada. carlos@db01.xxxxxx>
Después de esto, consigo ver algunas tablas, pero al cabo de un rato:
ERROR en línea 1: ORA-03113: fin de archivo en el canal de comunicación ERROR: ORA-03114: no conectado a ORACLE
Y a partir de entonces, no arranca.
Otra vez:
carlos@db01.xxxxxx> connect / as sysdba Conectado a una instancia inactiva. carlos@db01.xxxxxx> STARTUP mount Instancia ORACLE iniciada. Total System Global Area 612368384 bytes Fixed Size 1250452 bytes Variable Size 67111788 bytes Database Buffers 541065216 bytes Redo Buffers 2940928 bytes Base de datos montada. carlos@db01.xxxxxx> alter database datafile 5 offline drop 2 / Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 6 offline drop 2 / Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 7 offline drop 2 / Base de datos modificada. carlos@db01.xxxxxx> alter database datafile 8 offline drop 2 / Base de datos modificada. carlos@db01.xxxxxx> alter database open; Base de datos modificada. carlos@db01.xxxxxx>
La base de datos está abierta, pero todos los objetos (¡todos los que me importan!) que están en esos datafiles están kaputt, K.O., muertos sin remisión.
El culpable parece ser el ‘hardware’: han venido apareciendo errores varios (y extraños) en diferentes aplicaciones. Un ejemplo: tras copiar datos de un CD al HD, los ficheros cantan errores de CRC!
Resultado: Pedir un equipo nuevo y reinstalar todo desde cero (y el trabajo de varios días a la basura…)
Hay días en los que uno no se debería levantar de la cama…
Nota para mí: Si estamos en ‘NOARCHIVELOG’ hacer ‘backups’ frecuentemente.
Saludos.
Carlos.