viernes, 24 de junio de 2011

Cómo determinar si solo son números?

Este post está destinado a compartir con uds. 2 formas para determinar si una cadena está formada solo por números.

1) La primera de estas 2 formas es a través de la siguiente función:

CREATE OR REPLACE FUNCTION es_numero(v_valor IN VARCHAR2) RETURN NUMBER IS
v_numero NUMBER;
BEGIN
v_numero := TO_NUMBER(v_valor);
RETURN 0;
EXCEPTION WHEN VALUE_ERROR THEN
RETURN 1;
END;

El comportamiento de la función es devolver un 0 si la cadena que le pasamos esta compuesta solo por numero y un 1 si no lo está.

Lógicamente deberán usar la función en un WHERE con la condición = 0 o = 1.


2) La segunda forma que quiero compartir con uds. es a través de expresiones regulares.
Para esto la expresión regular que utilizamos es REGEXP_LIKE junto
con '^[0-9]+$', esto indica que evaluará en la cadena que le pasemos si está compuesta únicamente por números del 0 al 9 incluyendolos.
REGEXP_LIKE nos devuelve 'true' or 'false'.

Ejemplos:

SELECT *
FROM dual
WHERE REGEXP_LIKE ('788asd975', '^[0-9]+$');

Devolverá FALSE

SELECT *
FROM dual
WHERE REGEXP_LIKE ('asdasd', '^[0-9]+$');

Devolverá FALSE

SELECT *
FROM dual
WHERE REGEXP_LIKE ('788975', '^[0-9]+$');

Devolverá TRUE


Espero les haya servido

Saludos!
Gondalf

martes, 21 de junio de 2011

Borrar filas duplicadas

De vez en cuando, por ejemplo por la falta de algún índice unico, puede suceder que insertemos registros duplicados en una de nuestras tablas.
Cuando notamos esta "duplicidad" seguramente querremos borrar todos los duplicados y dejar solo 1 registro, o no?
Habitualmente tenemos inconveniente es realizar este trabajo dado que borramos todos los registros involucrados en la duplicidad.

Para solucionar esto y asi poder borrar todos los duplicados salvo 1, debemos seguir algunos pasos.

Por ejemplo, vamos a cerar la tabla DUPLICADOS la cual va a tener 2 columnas:

SQL> create table duplicados (col1 number, col2 varchar2(20))

Hacemos algunos insert en la misma:

SQL> insert into duplicados values (1, 'primero')

SQL> insert into duplicados values (2, 'segundo')

SQL> insert into duplicados values (3, 'tercero')

Provocamos la duplicación de un registro:

SQL> insert into duplicados values (1, 'primero')

SQL> commit;

Bueno, como vemos tenemos un registro duplicado el cual podemos borrar de la siguiente manera:

SQL> delete from duplicados
2 where rowid not in
3 (select min(rowid)
4 from duplicados
5 group by col1, col2);

Para entender un poco lo que acabamos de hacer debemos prestar atención en el min(rowid), el cual de las dos filas duplicadas
solo va a borrar aquella con el menor rowid. Con esto nos aseguramos de borrar solo 1 de los 2 registros.

Para comprobar que ya no tenemos duplicados en la tabla ejecutamos el siguiente SELECT

SQL> select *
2 from duplicados
3 group by col1, col2
4 having count (*) > 1;

Espero les haya servido

Saludos!
Gondalf

jueves, 16 de junio de 2011

START WITH .... CONNECT BY

Para poder recorrer estructuras en forma de árbol usamos esta clausula.

Para hacer un ejemplo sencillo, supongamos que tenemos una tabla cargada como un arbol de categorías, en donde una categoría posee un posible padre, el mismo marcado por la columna “parent_id”.

Para recorrer todo una rama empezando por su id podemos hacer lo siquiente:

SQL> SELECT *
2 FROM categorías
3 START WITH id =
4 CONNECT BY PRIOR parent_id = id;
Lo que marca la dirección en que va a ser recorriendo el “arbol” es la claúsula PRIOR.

Si quisiéramos recorrer al revés, es decir desde una hoja hasta la raíz, debemos hacer:

SQL> SELECT *
2 FROM categorías
3 START WITH id =
4 CONNECT BY parent_id = PRIOR id;
A su vez, tenemos la pseudo-columna LEVEL, la cual nos brinda el “numero” de nivel en cual estamos, es decir que es un indicador de la profundidad del árbol en la cual nos encontramos (Oracle maneja hasta un nivel de profundidad de 255).

SQL> SELECT RPAD(' ', 2*(LEVEL-1)) || nombre
2 FROM categorías
3 START WITH parent_id IS NULL
4 CONNECT BY PRIOR parent_id = id;
Esto fue pantallazo general del tema pero sepan que existe mucho mas para investigar del START WITH y el CONNECT BY en Oracle

Espero les haya servido.

Saludos!
Gondalf

miércoles, 15 de junio de 2011

Filas Encadenadas

Qué son????

Cuando el tamaño de una fila supere el tamaño de un bloque de la base de datos, puede generarse una migración o un encadenamiento de la fila.

Cuando hablamos de filas migradas nos referimos a una fila que se mueve completa de un bloque a otro dejando en el bloque original un puntero.

Cuando hablamos de filas encadenadas nos referimos a filas que requieren más de un bloque para su almacenamiento.

Si nos encontramos en presencia de una tabla con gran cantidad de filas encadenadas o migradas quiere decir que la base de datos va a tener que realizar varias lecturas físicas para poder procesar los datos de una misma fila lógica.

Como evitamos entonces el encadenamientos? Seteando un valor adecuado de pctfree en nuestra tabla.
Otra solución es un expdp/impdp de las tablas en cuestion

Si quisiéramos solucionar el problema de filas encadenadas debemos seguir los siguientes pasos:

Paso 1:

Correr el script utlchain.sql el cual crea la tabla CHAINED_ROWS.

Paso 2:

Revisamos la/s tabla para ver si poseen filas encadenadas. De poseerlas se insertaran en la tabla CHAINED_ROWS.

SQL> ANALYZE TABLE LIST CHAINED ROWS INTO chained_rows;

Paso 3:

Creamos una tabla auxiliar la cual llenaremos con las “filas duplicadas” de nuestra tabla

SQL> CREATE TABLE aux AS
2 SELECT * from
3 WHERE rowid IN
4 (SELECT head_rowid
5 FROM chained_rows
6 WHERE table_name = ‘nuestra tabla’);

Paso 4:

Borramos las filas encadenadas de nuestra tabla

SQL> DELETE FROM
2 WHERE rowid IN
3 (SELECT head_rowid
4 FROM chained_rows
5 WHERE table_name = ‘nuestra tabla’);

Paso 5:

Volvemos a insertar las tablas antes encadenadas en nuestra tabla

SQL> INSERT INTO SELECT * FROM aux;

Paso 6:

Realizar nuevamente la verificación para cerciorarse de que no queden filas encadenadas

SQL> DELETE CHAINED_ROWS WHERE table_name = 'nuestra tabla';

SQL> ANALYZE TABLE nombre_de_la_tabla
2 LIST CHAINED ROWS INTO chained_rows;

SQL> SELECT * FROM chained_rows WHERE table_name = 'nuestra tabla';

Espero les haya servido

Saludos!
Gondalf

miércoles, 1 de junio de 2011

Diferentes seteos del parametro AUDIT_TRAIL

Seteando este parámetro, una vez seteado debemos reiniciar la base, podemos comenzar a auditar objetos en nuestra base de datos.

Los diferentes valores que le podemos setear son:

- none: Desactiva la auditoria en la base de datos.

- os: Activa la auditoria, dejando los registros de auditoría en un archivo en nuestro sistema operativo.

- db: Activa la auditoria, los registros de auditoría son escritos en nuestra base de datos. Mas precisamente en la tabla SYS.AUD$.

- db,extended: Activa la auditoria, dejando los registros de auditoría en nuestra base de datos. Mas precisamente en la tabla SYS.AUD$.
Ademas, completa los campos SQLBIND and SQLTEXT de la tabla SYS.AUD$, cabe aclarar que dichos campos son del tipo CLOB.

- xml: Activa la auditoria, en donde los registros de auditoría son escritos en formato XML en un archivo en el sistema operativo

- xml,extended: Igual a la opción anterior pero agregando los valores SQLBIND and SQLTEXT al archivo.

Espero les haya servido.

Saludos!
Gondalf