martes, 13 de abril de 2010

Listar parámetros indocumentados en Oracle

Los parámetros indocumentados son controles especiales que modifican el comportamiento de la base de datos, y pueden generar problemas inesperados si no se usan adecuadamente. Deben ser utilizados bajo recomendación específica del soporte. Se identifican fácilmente ya que comienzan típicamente con "_".

El comando de SQL*Plus show parameters lista los valores estandar de la base de datos, y también de aquellos parámetros indocumentados que hemos alterado explícitamente.

Hay veces que queremos experimentar con algún parámetro indocumentado (no en producción obviamente!), pero necesitamos conocer el valor por defecto que está actualmente en uso. Aquí va una consulta para listarlos, con el valor actual para la sesión y para la instancia.
set linesize 131
set pages 9999
col parameter for A30
col description for A40
col "Session Value" for A15
col "Instance Value" for A15

SELECT
a.ksppinm "Parameter",
a.ksppdesc "Description",
b.ksppstvl "Session Value",
c.ksppstvl "Instance Value"
FROM
x$ksppi a,
x$ksppcv b,
x$ksppsv c
WHERE
a.indx = b.indx
AND
a.indx = c.indx
AND
a.ksppinm LIKE '/_%' escape '/'
/
Para volver al valor estándar del parámetro, bastará eliminarlo del archivo de parámetros de la base, si lo hemos incluído en el mismo.

jueves, 4 de marzo de 2010

Expresiones regulares en SQL con 9i

Recibi un comentario de Laura con el siguiente problema:

"Estoy empezando a trabajar con oracle 9.2 y tengo que cambiar una sentencia que esta en mysql con expresiones regulares a oracle. La sentencia que tengo que pasar a oracle es la siguiente:

SELECT * FROM prueba WHERE (content REGEXP ?) AND (codigo = ?) AND (nombre = ?) GROUP BY mes

¿Alguien sabe como puedo pasar a oracle esta sentecia?"


A diferencia de sus sucesores, Oracle 9i tiene un limitado manejo de expresiones regulares, el cual está mas enfocado hacia PL/SQL y no tanto a SQL.

El paquete para usar expresiones regulares se llama owa_pattern. Basta hacer un desc owa_pattern en la consola para saber si tenemos acceso a el, en caso contrario solicitarlo al administrador.

La función para buscar ocurrencias en expresiones regulares dentro del paquete es:
match([cadena_entrada],[expresion_regular])
Retorna un valor booleano true o false. Y aquí está el dilema, en SQL no existe el tipo booleano como tal, por tanto el motor no 'entiende' que es lo que la función está retornando.

SQL> select owa_pattern.match('ejemplo','ej*o') from dual;

ORA-06552: PL/SQL: Statement ignored
ORA-06553: PLS-382: expression is of wrong type

La solución es crear una función traductora en PL/SQL para convertir el booleano retornado por match a un tipo válido en SQL, como por ejemplo un numérico. Este wrapper recibirá los mismos parámetros que la función original.
create or replace function sql_match (exp varchar2, regexp varchar2) return number as
begin
if (owa_pattern.match(exp, regexp)) then
return 1;
else
return 0;
end if;
end;
La ponemos en práctica:

SQL> select sql_match('ejemplo','ej.*o') res from dual;

RES
----------
1

Ahora esta función es perfectamente compatible con SQL, y podemos usarla para evaluar el valor de una columna:

Ejemplo: nombres de empleados que comienzan con 'A'
SQL> select ename, sql_match(ename,'^A.*') res from scott.emp;

ENAME RES
---------- ----------
SMITH 0
ALLEN 1
WARD 0
JONES 0
MARTIN 0
BLAKE 0
CLARK 0
SCOTT 0
KING 0
TURNER 0
ADAMS 1
JAMES 0
FORD 0
MILLER 0

14 rows selected
Ahora si, volviendo al problema original planteado por nuestra amiga, la traducción de MySQL a Oracle 9i queda:

SELECT * FROM prueba WHERE (sql_match(content, ?)=1) AND (codigo = ?) AND (nombre = ?) GROUP BY mes


Como dije anteriormente, en versiones a partir de 10g, contamos con expresiones regulares prontas para SQL, como la función REGEXP_LIKE. El ejemplo aplicado a este caso quedaría de esta forma:

SELECT * FROM prueba WHERE regexp_like(content, ?) AND (codigo = ?) AND (nombre = ?) GROUP BY mes

miércoles, 10 de febrero de 2010

Critical Patch Update Febrero 2010

Oracle lanzó el último 4 de febrero una actualización de seguridad para sus servidores Weblogic, para las siguientes versiones:

• Oracle WebLogic Server 11gR1 releases (10.3.1 and 10.3.2)
• Oracle WebLogic Server 10gR3 release (10.3.0)
• Oracle WebLogic Server 10.0 through MP2
• Oracle WebLogic Server 9.0, 9.1, 9.2 through MP3
• Oracle WebLogic Server 8.1 through SP6
• Oracle WebLogic Server 7.0 through SP7

Este patch es de extrema urgencia y se recomienda la inmediata aplicación. Tal es así que se adelantó a la próxima actualización agendada (Oracle lanza patches regulares a mitad de abril, julio, octubre y enero). En este caso, una vulnerabilidad en el manejador de nodos permite acceder sin autenticación.

Recientemente un experto de seguridad había afirmado en una convención de hackers que 9 de cada 10 bases de datos Oracle podían ser violadas externamente, gracias a una vulnerabilidad que el encontró (aunque no mostró pruebas de hechos concretados). Este experto inglés, autor de varios libros, ya ha detectado decenas de bugs en productos como SQL Server, DB2, Informix, y Oracle. La companía aparentemente no se manifestó sobre este asunto.

Cierto o no, lo más recomendable es estar precavidos.

Ver también:
http://www.oracle.com/technology/deploy/security/alerts.htm
http://www.reuters.com/article/idUSTRE6125FB20100203?type=technologyNews

jueves, 7 de enero de 2010

Como exportar e importar código PL/SQL en 9i

A medida que avanzan las versiones de Oracle, cada vez se hace más dificil encontrar documentación para las anteriores, como por ejemplo 8i y 9i. Por suerte existen los blogs :)

En tiempos de 9i, EXP e IMP eran las opciones para exportar e importar objetos en nuestro esquema de base de datos. A partir de Oracle 10g, existen versiones mejoradas como Data Pump, que repasaré en otro momento.

Una duda que surge es como exportar e importar el código PL/SQL de un esquema para tener un rápido backup/restore. Hay algunos métodos que se basan en capturar el código en archivos (ver artículo), pero a la hora de llevar el código rápidamente con sus grants, todo de una vez a otro lugar, lo mejor es usar EXP/IMP.

Primero que nada, debemos saber que EXP/IMP trabaja en cuatro modos:
  • TABLE
  • TABLESPACE
  • USER
  • FULL
Si queremos exportar el código, deberemos usar el modo USER, o FULL (todos los esquemas).
Ahora, la única forma que IMP recupera el código PL/SQL, es importando en modo FULL. Aunque parezca extraño, el modo de importación USER no lo recupera aunque hayamos hecho el export de la misma forma.

Hecha esta aclaración, pasamos a los comandos.

Generar el dump (en modo USER)

exp usuario/password file=/tmp/bck_usuario.dmp owner=usuario rows=N triggers=Y indexes=N constraints=N log=/tmp/bck_usuario.log

Importar el código (en modo FULL)

imp usuario/password file=/tmp/bck_usuario.dmp full=Y ignore=y indexes=N log=/tmp/bck_usuario.log

Observaciones
  • Junto con el export, estamos capturando las tablas también (sin datos). El método EXP no es muy flexible en este sentido. Sin embargo a la hora de importar, con el parámetro ignore=Y, estaremos ignorando los intentos de creación si las mismas ya existen en el destino.
  • Como IMP únicamente puede utilizarse en modo FULL, si queremos traer solamente un usuario entonces deberemos generar un export de tipo USER.

viernes, 18 de diciembre de 2009

Cómo saber el tipo de Linux para instalar Oracle

Alguna vez caímos en paracaídas a instalar algún producto Oracle en un servidor Linux desconocido, e inmediatamente surgieron las siguientes interrogantes:
  • ¿Qué versión de Linux es?
  • ¿Cuál es la versión de Oracle que debo descargar?
La base de datos Oracle es el producto más portable del mercado, y por eso dispone de muchas versiones dependiendo de la arquitectura y versión del sistema operativo. Todo dba se ha visto confundido más de una vez al momento de elegir la versión correcta.

Por ese motivo recomiendo tener esta guía-ayuda a mano, para no perder tiempo a la hora de elegir.

Mapea los códigos informados por el comando Unix uname, con la versión de Linux que aparece en la página de downloads de Oracle. Basta con observar los últimos tres identificadores que aparecen en la salida del comando.
Por ejemplo para el primer caso sería "i686 i686 i386".

Espero que ayude!

$ uname -a
Linux hostname 2.6.9-34.0.2.ELsmp #1 SMP Fri Jun 30 10:33:58 EDT 2006 i686 i686 i386 GNU/Linux
-->
Linux x86: (32-bit OS)

$ uname -a
Linux hostname 2.6.9-55.ELsmp #1 SMP Fri Apr 20 16:36:54 EDT 2007 x86_64 x86_64 x86_64 GNU/Linux
-->
Linux x86_64: (64-bit OS)

$ uname -a
Linux hostname 2.6.9-42.EL #1 SMP Wed Jul 12 23:25:09 EDT 2006 ia64 ia64 ia64 GNU/Linux
-->
Linux Itanium: (64-bit OS)

$ uname -a
Linux hostname 2.6.9-34.0.1.0.11.EL #1 SMP Mon Dec 4 16:10:42 PST 2006 ppc64 ppc64 ppc64 GNU/Linux
-->
IBM Power Based Linux: (64-bit OS)

$ uname -a
Linux hostname 2.6.16.46-0.12-default #1 SMP Thu May 17 14:00:09 UTC 2007 s390x s390x s390x GNU/Linux
-->
IBM zSeries Based Linux: (64-bit OS)

$ uname -a
Linux hostname 2.4.21-50.EL #1 SMP Tue May 8 17:10:38 EDT 2007 s390 s390 s390 GNU/Linux
-->
IBM S/390 Based Linux (31-bit): (31-bit OS)