Quien soy? RSS feed Enviar por email Imprimir Parar este menu Ir arriba
Blogzote.com
Mexico, informatica, internet, musica y algo mas…
Pagina 3 de 6« Primera...2345...Ultima »

Registros duplicados en Oracle

Como suele pasar, se me olvido crear la llave primaria para una tabla, resultando que se insertaran registros duplicados en ella, ahora, ¿Cómo los elimino? Muy fácil, encontré, rascándole a google, una instrucción estándar para borrar registros duplicados:

1
2
3
4
5
DELETE FROM tabla
 WHERE ROWID NOT IN
            (SELECT MIN(ROWID)
               FROM tabla
              GROUP BY columna1, columna2, columna3...);

Donde por supuesto “tabla” es el nombre de la tabla y “columna1″, “columna2″, etc. Es la llave que identifica a cada registro.

* 22 Comentarios Email Imprimir

Procesar csv en oracle

Esta está facilita, me tope con la necesitad de procesar un archivo csv (comma separated values o valores separados por coma) con utl_file no tuve mayor problema para leer el archivo, ¿pero la cadena (o registro) del archivo, como la leo? Fácil, cree una función a la que se le manda la cadena a procesar y la posición de la columna que deseas y te regresa su valor.

Si tienes por ejemplo la cadena:

1
11111,22222,33333,44444,55555

Necesitas sacar de esa cadena el 3 campo, o sea, el valor “33333″, solo generas la llamada a la función:

1
variable := get_string_value (3,11111,22222,33333,44444,55555);

Aquí les dejo la función:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
--
  -- GET_STRING_VALUE
  --
  -- return the string value for a string id "p_string_id"
  -- in a csv string "p_string"
  -- 
  FUNCTION get_string_value (
     p_string_id            IN      NUMBER,
     p_string               IN      VARCHAR2) 
     RETURN VARCHAR2 IS
 
     v_string_value VARCHAR2(200);
  BEGIN
 
    IF (INSTR(p_string,',') > 0) AND
       (p_string_id         > 0) THEN
       IF p_string_id = 1 THEN
          v_string_value := SUBSTR(p_string, 0, INSTR(p_string,',',1,1)-1);
       ELSE
         IF (INSTR(p_string,',',1,p_string_id-1) > 0) AND
            (INSTR(p_string,',',1,p_string_id)   > 0) THEN			
            v_string_value := SUBSTR(p_string, INSTR(p_string,',',1,p_string_id-1)+1, 
                                              (INSTR(p_string,',',1,p_string_id)-1 - 
                                               INSTR(p_string,',',1,p_string_id-1)));
         ELSIF
            (INSTR(p_string,',',1,p_string_id-1) > 0) AND
            (INSTR(p_string,',',1,p_string_id)   = 0) THEN			
            v_string_value := SUBSTR(p_string, INSTR(p_string,',',1,p_string_id-1)+1, 
                                             (LENGTH(p_string) - 
                                               INSTR(p_string,',',1,p_string_id-1)));
         END IF;
       END IF; 
    END IF;
 
    RETURN v_string_value;
 
  END get_string_value;

Por supuesto no es la única forma de procesar una cadena con valores separados por coma, acá tengo otra forma mediante un loop:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DECLARE
  v_line      VARCHAR2(1000);
  v_value     VARCHAR2(100);  
  v_index     NUMBER;
BEGIN
  v_line  := '11111,22222,33333,44444,55555';
  v_index := 0;
  FOR i IN 1.. LENGTH(v_line) LOOP
      IF (SUBSTR(v_line, i, 1) = ',') OR
         (LENGTH(v_line)       = i  ) THEN
         --aqui lo que deseas hacer para cada valor 
         --v_value tendra el valor del campo 
         v_value := REPLACE(SUBSTR(v_line, v_index+1, (i-v_index)), ',','');
         v_index := i;
      END IF;
  END LOOP;
END;
* 2 Comentarios Email Imprimir

Oracle UTL_FTP

Hace unos me surgió la necesidad de realizar el paso de algunos archivos planos entre servidores, el problema es que este paso se va a realizar constantemente, entonces tuve que pensar en una solución que fuera fácil, aparte esos archivos no son mas que información que se procesa e ingresa a una tabla de base de datos.

De entrada la solución que se proponía era realizar un shell script para realizar el paso de archivos vía ftp de un servidor a otro, soluciona el problema pero no estaba muy de acuerdo, primero tener que llamar a un shell para después conectarte a Oracle y llamar a un procedimiento, le quita el control a Oracle sobre el manejo de esos archivos, otra era usar directamente UTL_FILE, pero este paquete sirve para el manejo de archivos en el mismo servidor de base de datos, que yo sepa, con utl_file no se puede manejar archivos de otras maquinas.

Tiempo atrás ya había leído de la existencia de un paquete para el manejo de conexiones tcp, el paquete se llama UTL_TCP, suponía entonces que ya debería de existir algo relacionado con el manejo de archivos entre servidores, la opción lógica era buscar el paquete UTL_FTP pero sorpresa, este no existe, bueno y ¿que dice Google al respecto? le di buscar utl_ftp y me regreso varias paginas, me encontré primero con un script guardado en sourceforce llamado “plsqlftp“, pero no me convenció, su desarrollo se ve casi abandonado y no encontré un solo ejemplo de cómo se usa, acabe descartándolo.

Rascándole un poquito mas a los resultados me tope con el que finalmente implemente, le llamaron “FTP Interfase“, me quedo perfecto para lo que necesitaba, se ve bastante robusto y completo, yo solo use tres funciones, “VERIFY_SERVER”, “PUT” y “GET” pero tiene muchas mas, igual más adelante las pueda necesitar, aquí les dejo el procedimiento que generé para realizar los movimientos de archivos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  --
  -- MOVE_FILE
  --
  -- move file "p_filename" with ftp interfase, use put or get "p_type_move
  -- "p_type_move" = "PUT" => from "p_localpath" to "p_remotepath"
  -- "p_type_move" = "GET" => from "p_remotepath" to "p_localpath"
  -- use ftp server "p_hostname" with usr "p_username" and pwd "p_password"
  --   
  PROCEDURE move_file    (
     p_type_move           IN      VARCHAR2,
     p_localpath           IN      VARCHAR2,
     p_remotepath          IN      VARCHAR2,
     p_filename            IN      VARCHAR2, 
     p_username            IN      VARCHAR2,
     p_password            IN      VARCHAR2,
     p_hostname            IN      VARCHAR2,
     p_error               OUT     VARCHAR2) IS
 
     v_exception    EXCEPTION;
     p_status       VARCHAR2(32000);
     p_bytes_trans  NUMBER;
     p_trans_start  DATE;
     p_trans_end    DATE;
     dummy          BOOLEAN;
  BEGIN
 
     IF (p_type_move != 'PUT') AND
        (p_type_move != 'GET') THEN
        p_error := 'ERROR: value for p_type_move not supported.';
        RAISE v_exception;
     END IF;
 
     dummy := ftp_interface.verify_server ( 
                    p_remotepath           => p_remotepath,
                    p_username             => p_username,
                    p_password             => p_password,
                    p_hostname             => p_hostname,
                    v_status               => p_status,
                    v_error_message        => p_error,
                    p_port                 => 21,
                    p_filetype             => 'ASCII',
                    p_mainframe_connection => FALSE );
 
     IF p_status != 'SUCCESS' THEN
        RAISE v_exception;
     END IF;
 
	 IF p_type_move = 'PUT' THEN
 
	     dummy := ftp_interface.put (
                    p_localpath            => p_localpath,
                    p_filename             => p_filename,
                    p_remotepath           => p_remotepath,
                    p_username             => p_username,
                    p_password             => p_password,
                    p_hostname             => p_hostname,
                    v_status               => p_status,
                    v_error_message        => p_error,
                    n_bytes_transmitted    => p_bytes_trans,
                    d_trans_start          => p_trans_start,
                    d_trans_end            => p_trans_end,
                    p_port                 => 21,
                    p_filetype             => 'ASCII',
                    p_mainframe_ftp        => FALSE,
                    p_mainframe_cmd        => '' );
 
         IF p_status != 'SUCCESS' THEN
            RAISE v_exception;
         END IF;
 
     ELSIF p_type_move = 'GET' THEN
 
		 dummy := ftp_interface.get (
                    p_localpath            => p_localpath,
                    p_filename             => p_filename,
                    p_remotepath           => p_remotepath,
                    p_username             => p_username,
                    p_password             => p_password,
                    p_hostname             => p_hostname,
                    v_status               => p_status,
                    v_error_message        => p_error,
                    n_bytes_transmitted    => p_bytes_trans,
                    d_trans_start          => p_trans_start,
                    d_trans_end            => p_trans_end,
                    p_port                 => 21,
                    p_filetype             => 'ASCII',
                    p_mainframe_ftp        => FALSE,
                    p_mainframe_cmd        => '' );
 
         IF p_status != 'SUCCESS' THEN
            RAISE v_exception;
         END IF;
 
     END IF;
 
     p_error := 'OK';
 
  EXCEPTION 
     WHEN v_exception THEN
         NULL;
     WHEN OTHERS THEN
         p_error := 'ERROR: ' || SQLERRM;
  END move_file;

La llamada al procedimiento se realiza de manera muy fácil:

1
2
3
4
5
6
7
8
move_file('GET',
          '/datos',
          '/home',
          'test.txt',
          'usuario',
          'password',
          'ip_del_host',
          v_error);
* 49 Comentarios Email Imprimir

Heterogeneous Services

Hace unos días me surgió la necesidad de conectar mi base de datos Oracle xe con Mysql, quería intentar procesar unos datos de una tabla Mysql para después pasarlos a otra tabla, de entrada tenia la posibilidad de hacerlo con php, ¿pero cada que necesitara procesar datos tendría que hacer una pagina php? Por eso pensé mejor en conectar Oracle con Mysql, me sería mas fácil jalar los datos de Mysql, procesarlos con PL/SQL para después depositarlos en otra tabla Mysql.

Me tope con un concepto que Oracle llama “heterogeneous services” que no es más que una vía rápida para conectarse con otras bases de datos, en este caso Mysql, aquí los pasos que seguí para lograr la conexión, es importante mencionar que esto lo logre bajo Windows:

1) Descargar el producto llamado “Mysql connector/ODBC” para Windows por supuesto e instalarlo.

2) Es necesario crear una conexión vía ODBC, la opción se llama “Orígenes de datos ODBC” esta dentro de “herramientas administrativas”, dentro existen varias opciones, es necesario crearla bajo “System DNS”, al valor de “data source name” en este caso le llame “mysqldb”, los valores servidor, usuario, password, base de datos, etc. no son mas que los usados para conectarte normalmente a Mysql, tiene una opción para probar la conexión, es preferible probar desde ahí si se logra la conexión.

3) Dentro de la estructura de archivos de Oracle ya existe una carpeta llamada “HS”, dentro de esa carpeta existen otras dos “admin” y “bin”, dentro de la carpeta admin es necesario crear un archivo init“nombre de nuestro servicio”.ora quedando: initmysqldb.ora, dentro de el deben de ir las siguientes entradas:

HS_FDS_CONNECT_INFO = mysqldb
HS_FDS_TRACE_LEVEL = 0
HS_FDS_TRACE_FILE_NAME = mysqldb.trc
HS_AUTOREGISTER = TRUE

4) Dentro de la estructura de archivos de Oracle ya existe otra carpeta llamada
“NETWORK”, dentro de ella existe otra llamada “admin”, dentro de la carpeta admin existen tres archivos, “listener.ora”, “sqlnet.ora” y “tnsnames.ora” ( ya muchos los conocerán, el tnsnames.ora se usa para configurar las conexiones a base de datos oracle cuando se esta usando el resolver nombres por tnsnames, dentro del “sqlnet.ora” se define como “names.directory_path = (TNSNAMES, HOSTNAME)” pero eso es harina de otro costal) dentro del archivo “listener.ora” debe de insertarse una nueva entrada (por supuesto la ruta del producto puede variar según tu instalación):

(SID_DESC =
      (SID_NAME = mysqldb)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\10.2.0\server)
      (PROGRAM = hsodbc)
    )

Que junto con lo que ya tenía el archivo quedaría algo como (dependiendo de tu base de datos y servicios instalados, solo añadí la primera parte del contenido de archivo, debajo de eso no se toca el contenido):

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\10.2.0\server)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\10.2.0\server)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = mysqldb)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\10.2.0\server)
      (PROGRAM = hsodbc)
    )
  )
(…)

5) Al archivo “tnsnames.ora” se le añade una nueva entrada:

mysqldb =
   (DESCRIPTION=
      (ADDRESS= (PROTOCOL=tcp)
                (HOST=localhost)
                (PORT=1521)
     )
     (CONNECT_DATA =
         (SERVICE_NAME=mysqldb)
     )
     (HS = OK)
)

6) Bajas y subes el servicio de tu base de datos, en este caso se llama
“OracleXETNSListener”, una vez levantado entras a tu sql*plus, cuando instalas xe te crea un iconito que llama “Ejecutar línea de comandos SQL” que no es mas que sql*plus ejecutado en un ambiente MSDOS, para los que tengan otra versión de Oracle entran directo a su sql*plus y creas un Database link con el siguiente comando, observa que el usuario y password lleva comillas dobles y el using lleva comillas simples:

1
2
3
4
CREATE database link mysqldb 
 CONNECT TO “usuario_mysql" 
 identified by “password_mysql" 
 using ‘mysqldb’;

Listo, ahora pueden accesar a su base de datos Mysql desde Oracle, simplemente deben referenciar que el objeto viene del dblink, o sea “tabla@mysqldb”

Es importante mencionar que esto lo logre estando tanto Oracle como Mysql en la misma maquina, he intentado conectarlos estando Mysql en otro host pero hasta el momento no han sido exitosas mis pruebas, ahí se los dejo de tarea.

* 29 Comentarios Email Imprimir

Nuevos conceptos en oracle

Esta me causo mucha gracia y no la pude dejar pasar, apenas escribí un post sobre ofertas de trabajo ridículas y esta es una de esas, pero esta se la mato a las demás, no solamente por sus salarios de risa, si no por que quien sabe quien capturo la oferta, parece que la persona de recursos humanos encargada del registro de la ofertas en la pagina tenía mucha prisa y antes de irse a festejar su 14 de febrero, le dejo al policía de la puerta de su oficina que se capturara las ofertas de la empresa.

La única respuesta lógica que le encuentro es esa, que alguien que no conoce nada del tema transcribió un texto escrito en un post-it o algo así a la pagina de Internet, no pudo leer bien lo que le dejaron, y puso lo mas cercano que se le ocurrió, lo malo es que no fue una, sino tres veces, y eso por que no me meto con la otra burrada del titulo, “Gerente de DataBase Marketing (Programador PL/SQL)”, que tiene que ver un gerente de database marketing (quien sabe que haga ese puesto) con un programador pl/sql.

Cada que lo leo no puedo dejar de soltar una risa burlona, es que llegar a conceptos como “store prodicius” o “Fushion” o “Pacash” relacionados con Oracle, esta cañón, al principio hasta me hizo dudar, creí que lo escribieron en ingles o algo así, pero no, no checa.

Sin duda lo que quisieron decir es: store prodicius = store procedures, fushion = function y Pacash = package, aquí les dejo el texto de la oferta:

Gerente de DataBase Marketing (Programador PL/SQL)

  • Lic. o Ing. en Sistemas o carrera afin.
  • Programador Oracle con PL/SQL, store prodicius, Fushion, Pacash, Querys
  • Visual Basic
  • Java Deseable
  • Office, macros de Excel
  • Edad de 29 a 32 años

Aquí la oferta en el sitio original.

Y acá dejo la captura de pantalla por si llegan borrar la oferta del sitio original.

oferta laboral rara

PD. sorry luzware, pero estuvo bueno su “españinglish”.

* 2 Comentarios Email Imprimir

Pagina 3 de 6« Primera...2345...Ultima »