Ejecutar comando scp sin que pida contraseña el servidor de origen

En la siguiente entrada de blog explico como utilizar el comando scp (Secure Copy o SCP es un medio de transferencia segura de archivos informáticos entre un host local y otro remoto o entre dos hosts remotos, usando el protocolo Secure Shell (SSH)) de Linux o Unix que nos permite realizar la copia de un fichero/s de un servidor a otro. Esto es muy útil cuando has creado una shell por ejemplo en un servidor de desarrollo y quieres simplemente copiarla de manera idéntica en el servidor de producción.

Ejemplo de formato de scp

scp -p -r $usuario@$servidor:fichero dir/

Ejemplo conectados como root en el servidor “destino”:

# scp -p -r shell.sh root@servidor:/ruta

Esto copia el fichero shell.sh en el servidor “servidor” conectado como root en la ruta “/ruta”. Para que no pida la contraseña, en el servidor “servidor” debe existir en el “home” del root el fichero .rhosts donde se detalla el servidor “destino” y el usuario del servidor “destino” que queremos que no pida la contraseña.

Ejemplo de fichero .rhosts del servidor “servidor”

[root@servidor ~]# more .rhosts
 destino root
 destino pepe --> Poniendo esto al usuario "pepe" tampoco se le pediría contraseña

Crear un DAD con OEM Application Server Control en ORACLE OAS 10g

Con el objeto de mostrar formularios por el navegador y poder acceder a procedimientos y paquetes de un esquema a través de una dirección virtual necesitamos crear lo que se conoce como DAD. Es decir, un descriptor de acceso a base de datos.

Pincharemos sobre el enlace HTTP_Server. Nos saldrá la pantalla siguiente e iremos a la pestaña “Administración”

En la siguiente pantalla pulsaremos el enlace “Propiedades PL/SQL”.

Una vez dentro de la pantalla anterior, al final de la siguiente veremos los enlaces para poder crear los DAD´s que necesitemos.

A la derecha de la pantalla, saldrá el botón “Crear” que nos permite crear DAD´s. En la pantalla anterior podemos ver como ya existen 2 creados en este ejemplo, uno que si que funciona, flecha verde arriba, y otro que no. Flecha verde abajo. Probablemente, el que no funciona es debido a una mala definición en el fichero tnsnames.ora.

Para crear un DAD pulsaremos en el botón “Crear” y saldrá una pantalla como la que sigue … Hay que tener en cuenta que para que el DAD funcione tendremos que reiniciar el servidor HTTP.

En esta pantalla tenemos que seleccionar el tipo de DAD que queremos crear. Si tenemos el OAS-portal instalado, podemos seleccionarlo, pero sino, podemos seleccionar General y funcionará seguro. Una vez seleccionado pulsaremos Continuar … Saldrá la pantalla siguiente donde podremos especificar la configuración de la conexión a la base de datos.

El nombre o ubicación de DAD será como una especie de directorio vitual que usaremos en la URL para acceder al esquema. En este ejemplo pondré “/dad_inf”. Seguidamente rellenaremos los campos con los datos del usuario que queramos que acceda para ejecutar su package, procedimiento o lo que sea que quiera ejecutar. En cadena de conexión pondremos el formato que se indica en el campo de debajo. Es decir, el nombre del servidor, el puerto, normalmente el 1521 por defecto y el nombre que tengamos especificado dentro del identificador en el fichero tnsnames.ora. Finalmente, especificaremos el idioma que tenemos en la Base de datos (podemos sacar estos valores consultando la tabla nls_database_parameters.

Ejemplo:

Con este ejemplo, ya podríamos probar el DAD, no hace falta rellenar las siguientes pantallas. Podríamos hacerlo posteriormente si queremos, simplemente pinchando en el enlace del DAD creado y accediendo al menú desplegable de la izquierda de la pantalla anterior.

En página por defecto ponemos el nombre del procedimiento que queremos que se ejecute si no se especifica ningún otro al escribir la url. Por ejemplo, si hemos llamado al descriptor midad y la página de inicio la ejecuta el procedimiento inicio, escribiremos inicio en página por defecto y cuando pongamos en el navegador http://misitio:XXXX/dad_inf, nos redirigirá a http://misitio:XXXX/dad_inf/inicio pero se puede dejar en blanco.

Para ejecutar cualquier prueba, podemos ir al navegador e intentar ejecutar cualquier procedimiento que tengamos creado para el usuario especificado en el DAD y ver que funciona.

Cómo saber si nuestro Unix o Linux es de 32 o 64 bits

Tanto en Unix como en Linux una manera sencilla de saber si nuestro sistema es de 32 o 64 bits es ejecuntando el comando uname desde la linea de comandos:

$ uname -a
Linux h0541.csub.scs.es 2.6.18-308.16.1.el5 #1 SMP Tue Sep 18 07:21:07
EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

En este ejemplo se trata de un Linux de 64 bits.  Nos lo informa el x86_64. Sino sale esto es de 32 bits.

Cómo saber si nuestro Windows es de 32 o 64 bits

Muchas veces es necesario saber si nuestro Windows o el Windows donde vamos a instalar el software de Oracle es de 32 o 64 bits. Lo necesitamos saber basicamente para la elección del CD a instalar. Si nos equivocamos e intentamos instalar un software Oracle de 32 bits en uno de 64 bits o alrevés, podemos encontrarnos con errores que nos puedan despistar y resulta que es porque nos hemos equivocado al seleccionar el CD. Por este motivo es importante, antes de ponerse a instalar nada, elegir correctamente el CD de 32 o 64 bits.

Para saber si nuestro servidor o PC cliente donde se va a instalar el software Oracle es de 32 o 64 bits tenemos que hacer:

Windows 8
Abre el menú Inicio de Windows 8 y elige Sistema. Se muestra una ventana. Arriba te indica la versión. Por la mitad, en la línea Tipo de sistema, aparece si el sistema operativo es de 32 o 64 bits.

Windows 7
Entra en el menú Inicio, haz clic con el botón derecho del ratón en Equipo y luego pincha en Propiedades. Se abrirá la ventana Sistema. Entre otras cosas te dice tu versión de Windows y de Service Pack y el número de bits.

Windows XP y Windows Vista
Esto lo podemos hacer de 2 maneras:

La primera ejecutándo desde el menú el sysdm para sacar las propiedades del sistema o bien accediendo a la misma pantalla mediante el ratón.

Primera opción:
1.    Entra en el menú Inicio y haz clic en Ejecutar (abajo, a la derecha).
2.    Escribe en la ventana sysdm.cpl y pulsa Enter o Aceptar.
3.    Pincha en la pestaña General.
Si tu Windows XP es de 64 bits deberás ver x64 justo después del nombre de la versión (Windows XP Professional x64 Edition Versión). Si no pone nada significa que es de 32 bits.

Segunda opción:

En el icono Mi PC, pulsar botón derecho y saldrá la pantalla siguiente de propiedades del sistema o también desde Inicio -> Panel de control -> Sistema y mantenimiento -> Sistema.

En este ejemplo, como no sale nada de x64 significa que es de 32 bits.

Si tu Windows XP es de 64 bits deberás ver x64 justo después del nombre de la versión (Windows XP Professional x64 Edition Versión). Si no pone nada significa que es de 32 bits.

NOTA:
En los CD´s originales de Oracle, si la versión es de 32 bits no suele tampoco poner nada. Sin embargo, si la versión es de 64 bits lo indica expresamente en el mismo CD al lado del nombre del producto.

Crear una tabla con contenido mediante database link de una base de datos a otra

En la siguiente entrada de Blog, voy a explicar como crear una tabla con contenido en una base de datos Oracle accediendo a otra base de datos Oracle mediante un database Link. Además voy a mostrar que la creación de la tabla en destino puede presentar diferencias de storage dependiendo de cómo la creemos. Si queremos que sea idéntica a la de origen, tendremos que copiar sus parámetros de storage en la sentencia de creación. Esto es una manera de crear una tabla con contenido sin necesidad de utilizar las utilidades exp/imp ni expdp/impdp.

Esto es muy útil cuando queremos crear una tabla que tenemos en Desarrollo o Pre-producción y queremos pasarlo al entorno de producción.

Para el ejemplo daré por hecho que tenemos un Data Base Link creado que permite acceder a la Base de datos de destino. Un database link se crea de la siguiente manera:

CREATE PUBLIC DATABASE LINK "MY_DBLINK"
CONNECT TO USUARIO_PRUEBA
IDENTIFIED BY  "<pwd_usuario>"
USING '<cadena_conexión>'; -- Esto consiste en una cadena de conexión que debe estar en tnsnames.ora

Puedes ampliar información sobre DBLinks aqui

Para comprobar que el DBLink funciona, podemos hacer la consulta hacia la tabla que queremos copiar de la siguiente  manera:

SQL> SELECT * FROM USUARIO_PRUEBA.TABLA@MY_DBLINK;

 Ahora creamos la tabla con el contenido de la siguiente manera:

- Primero nos conectamos a la Base de datos, con el usuario que corresponda, donde queremos crear la tabla con el contenido:

sqlplus usuario_prueba@cadena_conexion

- Ahora creamos la tabla …

SQL> CREATE TABLE usuario_prueba.nombre_tabla AS SELECT * from USUARIO_PRUEBA.TABLA@MY_DBLINK;

Esta sentencia creará la tabla en el destino con su contenido, pero los parámetros de STORAGE serán los que tenga el tablespace donde esta asignado “usuario_prueba”. Es decir, no cogerá los valores de STORAGE que tiene la tabla en origen.

Ahora probaremos con otro ejemplo, donde si detallamos el STORAGE que queremos y el tablespace donde queremos ubicar la tabla.

CREATE TABLE usuario_prueba.nombre_tabla
 TABLESPACE tablespace
 PCTUSED    40
 PCTFREE    10
 INITRANS   1
 MAXTRANS   255
 STORAGE    (
 INITIAL          10016K
 NEXT             10000K
 MINEXTENTS       1
 MAXEXTENTS       499
 PCTINCREASE      0
 FREELISTS        1
 FREELIST GROUPS  1
 BUFFER_POOL      DEFAULT
 )
 LOGGING
 NOCACHE
 NOPARALLEL AS SELECT * FROM USUARIO_PRUEBA.TABLA@MY_DBLINK;

En este otro ejemplo, el storage que tendrá la tabla será el especificado en la misma sentecia CREATE TABLE, y los datos los cogerá exactamente igual que la sentencia anterior.

ORA-00054: recurso ocupado y obtenido con NOWAIT especificado o timeout vencido || Bloqueos

Este error suele aparecer cuando existen bloqueos esperando a que otro usuario termine una operación, para poder realizar la suya. Uno de los más comunes que suelen suceder  es cuando se hacen “truncate” o “drop” de tablas y no nos deja hacerlo porque las tabla/s están bloqueada/s por otros procesos de ese mismo u otros usuarios.

En el ejemplo que explico seguidamente el problema se produjo porque al llenarse un tablespace (datafile al 100%) realizando unos “inserts” en una tabla, el proceso se quedó bloqueado hasta poder hacer la inserción. En  mi caso, como podía volver a lanzar el proceso sin problema, y no quería ampliar más la ocupación del tablespace afectado. Decidí matar los procesos que estaban bloqueados y volver a lanzar la ejecución de los inserts que provocaron por error que se llenara el tablespace.

En este ejemplo sólo se va a tratar el problema del bloqueo, no se va a tener en cuenta el problema de la falta de espacio del tablespace, porque eso fue debido a otra causa, pero que fue, en parte el causante del error que os voy a explicar y cuya solución veréis en esta entrada de blog.

Entro en detalle:

Al intentar hacer un truncate de una tabla salta el error:

ORA-00054: recurso ocupado y obtenido con NOWAIT especificado o timeout vencido

SQL> truncate table <mi_tabla> ;
truncate table <mitabla>
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

Esto ocurre porque se ha bloqueado uno o varios registros mediante setencias SQL. Select´s especificados como “NO WAIT” o “FOR UPDATE NOWAIT” o por una operación DDL que fue bloqueada. La solución podía pasar por hacer el commit o rollback. El commit no funcionó porque no hay espacio en el tablespace. El rollback no se probó, porque preferí matar la sesión que estaba provocando el error tal y como explico seguidamente.

En Oracle hay una vista llamada v$lock que nos indica los objetos que se encuentran en bloqueo, el identificador de usuario,  sesion y el tipo de bloqueo. Una join con la tabla dba_objects nos proporcionará ademas el nombre y tipo de los objetos bloqueados. La consulta seria como sigue:

SELECT
     decode(L.TYPE,'TM','TABLE','TX','Record(s)') TYPE_LOCK,
     decode(L.REQUEST,0,'NO','YES') WAIT,
     S.OSUSER OSUSER_LOCKER,
     S.PROCESS PROCESS_LOCKER,
     S.USERNAME DBUSER_LOCKER,
     O.OBJECT_NAME OBJECT_NAME,
     O.OBJECT_TYPE OBJECT_TYPE,
     CONCAT(' ',s.PROGRAM) PROGRAM,
     O.OWNER OWNER
 FROM v$lock l,dba_objects o,v$session s
 WHERE l.ID1 = o.OBJECT_ID AND s.SID =l.SID AND l.TYPE in ('TM','TX','UL');

Existen varios tipos de bloqueo (TM,TX,UL):

TM – DML enqueue. Bloqueos a nivel de tabla. Los bloqueos a nivel de tabla son creados cuando se ejecuta una sentencia DML del tipo: update, insert, delete, select ..for update sobre la tabla entera.

Por ejemplo:

DELETE from <mi_tabla>;
TRUNCATE <mi_tabla>;
UPDATE <mi_tabla> SET campo1 = valor;

haciendo un “delete” fue el error en este ejemplo. Por tanto tenía un bloqueo a nivel de tabla.

TX – Transaction enqueue. Bloqueos a nivel de fila. Los bloqueos a nivel de fila se crean cuando se ejecutan senencias DML contra un conjunto de registros específicos.

UL – User supplied.  Bloqueos a nivel de usuario.

Para solucionar el error:

Nos conectaremos como system a Oracle y ejecutaremos la siguiente consulta para ver si existe algún bloqueo:

 SQL> show user
 USER is "SYSTEM"
 SQL> select * from v$lock where request!=0;

Si hacemos una join con v$open_cursor podremos ver que consulta es la que se encuentra parada a la espera de que se produzca el desbloqueo para poder ejecutarse.

En la consulta siguiente podemos ver las sentencias paradas esperando a que termine un bloqueo, la sentencia que quieren ejecutar y el id de proceso que las está bloqueando:

select /*+ ordered
    no_merge(L_WAITER)
    no_merge(L_LOCKER) use_hash(L_LOCKER)
    no_merge(S_WAITER) use_hash(S_WAITER)
    no_merge(S_LOCKER) use_hash(S_LOCKER)
    use_nl(O)
    use_nl(U)
    */
    /* first the table-level locks (TM) and mixed TM/TX TX/TM */
    S_LOCKER.OSUSER OS_LOCKER,
    S_LOCKER.USERNAME LOCKER_SCHEMA,
    S_LOCKER.PROCESS LOCKER_PID,
    S_WAITER.OSUSER OS_WAITER,
    S_WAITER.USERNAME WAITER_SCHEMA,
    S_WAITER.PROCESS WAITER_PID,
    'Table lock (TM): '||U.NAME||'.'||O.NAME||
    ' - Mode held: '||
    decode(L_LOCKER.LMODE,
    0, 'None', /* same as Monitor */
    1, 'Null', /* N */
    2, 'Row-S (SS)', /* L */
    3, 'Row-X (SX)', /* R */
    4, 'Share', /* S */
    5, 'S/Row-X (SSX)', /* C */
    6, 'Exclusive', /* X */
    '???: '||to_char(L_LOCKER.LMODE))||
    ' / Mode requested: '||
    decode(L_WAITER.REQUEST,
    0, 'None', /* same as Monitor */
    1, 'Null', /* N */
    2, 'Row-S (SS)', /* L */
    3, 'Row-X (SX)', /* R */
    4, 'Share', /* S */
    5, 'S/Row-X (SSX)', /* C */
    6, 'Exclusive', /* X */
    '???: '||to_char(L_WAITER.REQUEST))
    SQL_TEXT_WAITER
from
    V$LOCK L_WAITER,
    V$LOCK L_LOCKER,
    V$SESSION S_WAITER,
    V$SESSION S_LOCKER,
    sys.OBJ$ O,
    sys.USER$ U
where S_WAITER.SID = L_WAITER.SID
    and L_WAITER.TYPE IN ('TM')
    and S_LOCKER.sid = L_LOCKER.sid
    and L_LOCKER.ID1 = L_WAITER.ID1
    and L_WAITER.REQUEST > 0
    and L_LOCKER.LMODE > 0
    and L_WAITER.ADDR != L_LOCKER.ADDR
    and L_WAITER.ID1 = O.OBJ#
    and U.USER# = O.OWNER#
union
    select /*+ ordered
        no_merge(L_WAITER)
        no_merge(L_LOCKER) use_hash(L_LOCKER)
        no_merge(S_WAITER) use_hash(S_WAITER)
        no_merge(S_LOCKER) use_hash(S_LOCKER)
        no_merge(L1_WAITER) use_hash(L1_WAITER)
        no_merge(O) use_hash(O)
        */
        /* now the (usual) row-locks TX */
        S_LOCKER.OSUSER OS_LOCKER,
        S_LOCKER.USERNAME LOCKER_SCHEMA,
        S_LOCKER.PROCESS LOCK_PID,
        S_WAITER.OSUSER OS_WAITER,
        S_WAITER.USERNAME WAITER_SCHEMA,
        S_WAITER.PROCESS WAITER_PID,
        'TX: '||O.SQL_TEXT SQL_TEXT_WAITER
    from
        V$LOCK L_WAITER,
        V$LOCK L_LOCKER,
        V$SESSION S_WAITER,
        V$SESSION S_LOCKER,
        V$_LOCK L1_WAITER,
        V$OPEN_CURSOR O
    where S_WAITER.SID = L_WAITER.SID
        and L_WAITER.TYPE IN ('TX')
        and S_LOCKER.sid = L_LOCKER.sid
        and L_LOCKER.ID1 = L_WAITER.ID1
        and L_WAITER.REQUEST > 0
        and L_LOCKER.LMODE > 0
        and L_WAITER.ADDR != L_LOCKER.ADDR
        and L1_WAITER.LADDR = L_WAITER.ADDR
        and L1_WAITER.KADDR = L_WAITER.KADDR
        and L1_WAITER.SADDR = O.SADDR
        and O.HASH_VALUE = S_WAITER.SQL_HASH_VALUE
/

Pero sino devuelve nada, que era lo que me pasaba a mi, y como el error me lo generaba un delete o un truncate, tuve que ejecutar la siguiente consulta para ver que era lo que tenía que “matar”.

SQL> SELECT mode_held FROM dba_dml_locks where OWNER='<mi_usuario>';
MODE_HELD
-------------
Row-X (SX)
Row-X (SX)
Row-X (SX)

Seguidamente podía listar los bloqueos que ocurrían en ese momento en la base de datos.Y  por medio de los campos LMODE y REQUEST saber de que tipo son :

none
null (NULL)
row-S (SS)
row-X (SX)
share (S)
S/Row-X (SSX)
exclusive (X)

SELECT oracle_username || ' (' || s.osuser || ')' username
    ,  s.sid || ',' || s.serial# sess_id
    ,  owner || '.' || object_name object
    ,  object_type
    ,  decode( l.block
       ,       0, 'Not Blocking'
       ,       1, 'Blocking'
       ,       2, 'Global') status
    ,  decode(v.locked_mode
      ,       0, 'None'
      ,       1, 'Null'
      ,       2, 'Row-S (SS)'
      ,       3, 'Row-X (SX)'
      ,       4, 'Share'
      ,       5, 'S/Row-X (SSX)'
      ,       6, 'Exclusive', TO_CHAR(lmode)) mode_held
FROM v$locked_object v,dba_objects d,v$lock l,v$session s
WHERE v.object_id = d.object_id
   and v.object_id = l.id1
   and v.session_id = s.sid
ORDER BY oracle_username,session_id
/

Sale algo como …

Intento matarlo …

SQL> alter system kill session '215,2774';
alter system kill session '215,2774'
*
ERROR at line 1:
ORA-00031: session marked for kill

Pruebo entonces con immediate y si me funciona.

alter system kill session '215,2774' immediate;

Pero si lo anterior fallase buscaría por medio de esta SQL el  SPID que es el número de proceso de Linux/unix que usaría para matar el proceso a nivel de S.O.

SELECT s.sid, p.spid, s.osuser, s.program
FROM   v$process p, v$session s
WHERE  p.addr = s.paddr;

La consulta anterior me muestra todos los procesos, buscaría el SID del proceso que quiero matar y me anotaría el campo SPID que es el que definitivamente usaré para matar el proceso. Pero si quiero sólo buscar el SID de la que quiero matar, ejecutaría:

SELECT s.sid, p.spid, s.osuser, s.program
FROM   v$process p, v$session s
WHERE  p.addr = s.paddr and s.sid = '215'; --> SID basado en mi ejemplo

Para saber cual es el SPID busco con el campo SID que me salia en la primera consulta. Es el primer valor antes de la “,” que uso en el” alter kill session …”

Para matar el proceso a nivel de S.O en mi caso un Linux. Se hace así:

Conectado como root al linux …

# ps -ef |grep  <SPID> --> Donde SPID es el número de proceso
# kill -9 <SPID>

Que GRANT se puede asignar en función del objeto destino en ORACLE

Según el objeto de que se trate, en Oracle podemos dar los siguientes privilegios:

Tables: select, insert, update, delete, alter, debug, flashback, on commit refresh, query rewrite, references, all
Views: select, insert, update, delete, under, references, flashback, debug
Sequence: alter, select
Packages, Procedures, Functions (Java classes, sources…): execute, debug
Materialized Views: delete, flashback, insert, select, update
Directories: read, write
Libraries: execute
User defined types: execute, debug, under
Operators: execute
Indextypes: execute

 

Manipular una tabla de un entorno Oracle desde otro entorno Oracle mediante DBLINK

Probablemente como administradores de Oracle nos habrán solicitado lo siguiente:

Querer consultar o modificar una tabla que está en un Servidor Oracle con un usuario que está en otro servidor Oracle.

Para poder realizar esta tarea, basta con crear un dblink entre ambas bases de datos y crearlo de manera PUBLIC y posteriormente asignar los privilegios(GRANT) de la tabla que queremos poder ver a PUBLIC. Dicha asignación de permisos a PUBLIC la realizaremos en el servidor Oracle donde está la tabla que queremos ver. Para ver que tipo de GRANT podemos asignar puedes consultar esta entrada de blog.

Ejemplo:

En el servidor “origen” creamos el dblink public:

CREATE PUBLIC DATABASE LINK "DBLINK_DESTINO"
CONNECT TO SYSTEM --> o el usuario que queramos usar
IDENTIFIED BY "<pwd>"
USING 'CADENA_CONEXION_DESTINO'; --> que existirá en tnsnames.ora 
del servidor Origen y donde se especifica el servidor, puerto, etc...
donde conectaremos cuando hagamos las consultas

Luego en el servidor “destino”:

Ejecutaremos desde sqlplus por ejemplo y con el propietario de la tabla en cuestión:

GRANT ALL ON <nombre_propietario>.<nombre_tabla> TO PUBLIC;

Para mejorar lo anterior y evitar tener que escribir el nombre del propietario en las consultas, podemos crear un sinónimo de esta manera:

CREATE PUBLIC SYNONYM <nombre_tabla> FOR <nombre_propietario>.<nombre_tabla>;

Lo importante de las sentencias anteriores es especificar “PUBLIC” de esta manera los privilegios se hacen disponibles a todos los usuarios de la base de datos. Y mediante el dblink, también lo haces disponibles a aquellos usuarios que puedan conectarse mediante ese dblink, que en este ejemplo son todos.

Consulta usando like y que no diferencie mayúsculas de minúsculas

El “problemilla” que se plantea es el siguiente …

En una base de datos, en un campo en concreto, puede aparecer un texto en mayúsculas, y el mismo texto también en minúsculas. Debía encontrar la manera de hacer una consulta con la cláusula LIKE, y que me encontrase el texto, tanto en mayúsculas como en minúsculas.  Pero realizando la consulta con like sin antes pasarlo a mayúsculas o a minúsculas, Oracle sólo encuentra el texto tal y como lo escribes. Por tanto, lo que se quiere es que si se escribe un texto que lo encuentre tanto si está escrito de una forma como de otra.

Solución:
Pasar a mayúsculas el campo y también la cadena que buscamos dentro del LIKE. De manera que la búsqueda se hará siempre en mayúsculas, y por lo tanto, encontrará el texto esté guardado en mayúsculas o minúsculas e independientemente de que quien busque a su vez lo teclee en minúsculas.

Ejemplo

accept cadena varchar2(150);

SELECT * from TABLA_EJ
WHERE UPPER(campo) LIKE UPPER('%&cadena%');

Donde campo es el campo texto donde vamos a buscar la cadena y &cadena la cadena de caracteres en concreto que queremos buscar.

Muy fácil pero hay que tenerlo en cuenta.