Ir al contenido



Foto

SQL de Firebird a Oracle


  • Por favor identifícate para responder
34 respuestas en este tema

#1 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 06 agosto 2012 - 10:53

Que tal a todos.
Me he puesto en la tarea de explorar el mundo de Oracle con algo más de profundidad en el manejo del SQL procedimental o como es conocido PL/SQL. Para esto estoy trabajando con Firebird 2.1 y Oracle 11g Ex en un cara a cara de consultas sobre el diseño de base de datos que les enseñaré a continuación.

La idea es que teniendo bases en las consultas básicas y algunas otras más estructuradas en Firebird se puedan replantear para un entorno Oracle, así de esta manera espero sea más simple el cambio de manejo y costumbres a la hora de hacer consultas o procedimientos. Cualquiera puede participar y aportar "reglas de negocio" al ejercicio, que en un principio muy básico es una base de datos para un sistema call-center de soporte a usuarios. Se trata de que quienes conocen Oracle puedan orientarnos a la contraparte y así mismo conocer las cualidades de Firebird.

Entre más podamos plantear, más atractivo será el ejercicio, si bien pueden ser disparadores, consultas complejas, procedimientos, excepciones, etc.

La siguiente es la estructura de la base de datos:


/******************************************************************************/
/***                                Tablas                                ***/
/******************************************************************************/



CREATE TABLE CALL_CENTERS (
    ID_CALLCENTER  INTEGER NOT NULL,
    NOMBRE        VARCHAR(50),
    TELEFONO      VARCHAR(20),
    DIRECCION      VARCHAR(50),
    CIUDAD        VARCHAR(50)
);

CREATE TABLE CLIENTE (
    ID_CLIENTE  INTEGER NOT NULL,
    NOMBRES    VARCHAR(50),
    APELLIDOS  VARCHAR(50),
    TELEFONO    VARCHAR(20),
    DIRECCION  VARCHAR(50),
    CIUDAD      VARCHAR(50)
);

CREATE TABLE LLAMADAS_CLIENTE (
    ID_LLAMADAS      INTEGER NOT NULL,
    ID_CLIENTE        INTEGER NOT NULL,
    ID_CALLCENTER    INTEGER NOT NULL,
    ID_STAFF          INTEGER NOT NULL,
    ID_SOLUCION      INTEGER NOT NULL,
    FECHA            DATE,
    DESCRIPCION      VARCHAR(500),
    DETALLE_SOLUCION  VARCHAR(500),
    SOLUCIONADO      INTEGER
);

CREATE TABLE PROBLEMAS (
    ID_PROBLEMAS  INTEGER NOT NULL,
    DESCRIPCION  VARCHAR(200),
    DETALLES      VARCHAR(500)
);

CREATE TABLE SOLUCIONES (
    ID_SOLUCIONES  INTEGER NOT NULL,
    DESCRIPCION    VARCHAR(200),
    DETALLES      VARCHAR(500)
);

CREATE TABLE SOLUCIONES_PROBLEMAS (
    ID_SOLUCION  INTEGER NOT NULL,
    ID_PROBLEMA  INTEGER NOT NULL
);

CREATE TABLE STAFF (
    ID_STAFF  INTEGER NOT NULL,
    NOMBRES    VARCHAR(50),
    APELLIDOS  VARCHAR(50),
    TELEFONO  VARCHAR(20),
    DIRECCION  VARCHAR(50),
    CIUDAD    VARCHAR(50)
);



/******************************************************************************/
/***                              Primary Keys                              ***/
/******************************************************************************/

ALTER TABLE CALL_CENTERS ADD CONSTRAINT PK_CALLCENTER PRIMARY KEY (ID_CALLCENTER);
ALTER TABLE CLIENTE ADD CONSTRAINT PK_CLIENTE PRIMARY KEY (ID_CLIENTE);
ALTER TABLE LLAMADAS_CLIENTE ADD CONSTRAINT PK_LLAMADAS PRIMARY KEY (ID_LLAMADAS);
ALTER TABLE PROBLEMAS ADD CONSTRAINT PK_PROBLEMAS PRIMARY KEY (ID_PROBLEMAS);
ALTER TABLE SOLUCIONES ADD CONSTRAINT PK_SOLUCIONES PRIMARY KEY (ID_SOLUCIONES);
ALTER TABLE STAFF ADD CONSTRAINT PK_STAFF PRIMARY KEY (ID_STAFF);


/******************************************************************************/
/***                              Foreign Keys                              ***/
/******************************************************************************/

ALTER TABLE LLAMADAS_CLIENTE ADD CONSTRAINT FK_CALL_CENTER FOREIGN KEY (ID_CALLCENTER) REFERENCES CALL_CENTERS (ID_CALLCENTER);
ALTER TABLE LLAMADAS_CLIENTE ADD CONSTRAINT FK_CLIENTE FOREIGN KEY (ID_CLIENTE) REFERENCES CLIENTE (ID_CLIENTE);
ALTER TABLE LLAMADAS_CLIENTE ADD CONSTRAINT FK_STAFF FOREIGN KEY (ID_STAFF) REFERENCES STAFF (ID_STAFF);
ALTER TABLE SOLUCIONES_PROBLEMAS ADD CONSTRAINT FK_PROB_SOL FOREIGN KEY (ID_PROBLEMA) REFERENCES PROBLEMAS (ID_PROBLEMAS);
ALTER TABLE SOLUCIONES_PROBLEMAS ADD CONSTRAINT FK_SOL_PROB FOREIGN KEY (ID_SOLUCION) REFERENCES SOLUCIONES (ID_SOLUCIONES);




Y una gráfica del modelo relacional:

Archivos adjuntos


  • 0

#2 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 06 agosto 2012 - 11:00

Primera posible regla de negocio:


- Seleccionar y cuantificar la cantidad de problemas solucionados por mes y ordenarlas según el asesor quién atiende (staff)de mayor a menor.



Saludos!
  • 0

#3 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 06 agosto 2012 - 11:04

Adjunto una copia de la base de datos que hice con algunos registros para pruebas. Faltan datos.


Saludos!
  • 0

#4 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.084 mensajes
  • LocationRepública Dominicana

Escrito 07 agosto 2012 - 07:04

Saludos.

La primera observación que haré es la siguiente, los SP Selectable (creo que es el termino) difieren bastante. En Firebird solo haces Select * from SP, para Oracle tendrías que hacer un Execute o Call del SP.

En ese mismo sentido, para que un SP funcione como un "Select" en Oracle debes utilizar una variable tipo SYS_REFCURSOR.
Ejemplo.

Cabe señalar que los componentes tipo TStoredProc y sus parecidos o descendientes de Delphi cuando ejecutas un SP de este tipo tienen un delay considerable, para que funcione adecuadamente debes utilizar las librerías de DevArt, las cuales son de pago.

En su momento cuando nos toco enfrentar esta situación (un ex-compañero y yo), después de haber analizado varias alternativas optamos por  hacer bloques PL/SQL dentro del TSQLQuery así:
BEGIN
SELECT * FROM TABLA;
END;


Con lo anterior resolvimos ese problema.

Después de ahí prácticamente Firebird y Oracle son bastante similares en cuando a su lenguaje.
  • 0

#5 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 07 agosto 2012 - 07:41

Yo uso Oracle y ADO desde hace un par de años y me ha funcionado muy muy bien. El proveedor OleDb de Oracle es bastante eficiente. Por lo que no hace necesario el uso de componentes de terceros para optimizar el acceso a los procedimientos almacenados o en su defecto tablas....
  • 0

#6 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.084 mensajes
  • LocationRepública Dominicana

Escrito 07 agosto 2012 - 08:07

Saludos.

Una vez tratamos de utilizar ADO de Delphi 2007 con Oracle 10g y todo fue una catástrofe para un proyecto con Intraweb.

Funcionaba cuando quería por así decirlo, la experiencia fue bastante mala, por eso fue que empezamos a buscar opciones.
  • 0

#7 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 07 agosto 2012 - 08:09

Que extraño amigo mio... claro siempre es posible tener malas experiencias.  En lo personal me ha ido bastante bien con ADO con la mayoria de bases de datos.. Con excepción de Db2 sobre Iseries, todo ha ido muy bien
  • 0

#8 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 07 agosto 2012 - 03:46

Gracias compañeros por sus aportes y experiencias, siempre es bueno conocer este tipo de detalles.

Ahora bien, retornando un poco a la idea original y dando en cierta forma solución a la solicitud de consulta he realizado lo siguiente (presto a cualquier corrección claro está)


SELECT ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION, COUNT(*) FROM LLAMADAS_CLIENTE WHERE SOLUCIONADO = 1 AND FECHA BETWEEN '01/08/2012' AND '07/08/2012'
GROUP BY ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION ORDER BY ID_STAFF DESC


suponiendo por la aclaración de Rolphy, este no tendría diferencia en Oracle.

Otra de las cosas por aplicar es en el manejo de bucles. En Firebird existe la operación for select que realiza una consulta previa y con el resultado realiza la operación iteractiva que tengamos dentro. ¿De qué manera se emplea en Oracle?


Saludos!
  • 0

#9 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.084 mensajes
  • LocationRepública Dominicana

Escrito 07 agosto 2012 - 05:49

Saludos.

Para los bucles tienes la siguiente sentencia:

FOR DATA IN (SELECT * FROM TABLA)
LOOP
  -- Mis sentencias
END LOOP;


Siguiendo el ejemplo anterior, para acceder a los campos del Select debes usar el nombre del Alias que para este caso se llama "DATA" y sería así: DATA.CAMPO1, DATA.CAMPO2.

En cuanto al manejo de la fecha, te recomiendo el uso de la función TO_DATE (con esta función te ahorraras muchos dolores de cabeza) y si en el campo tipo Date almacenas horas también y en tu sentencia no quieres tomarla en cuenta pues la función TRUNC es muy buena.

Por lo que tu sentencia quedaría algo así:
SELECT ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION, COUNT(*) 
FROM LLAMADAS_CLIENTE
WHERE SOLUCIONADO = 1
AND TRUNC(FECHA) BETWEEN TO_DATE('01/08/2012', 'DD/MM/YYYY') AND TO_DATE('07/08/2012', 'DD/MM/YYYY')
GROUP BY ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION
ORDER BY ID_STAFF DESC

  • 0

#10 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 07 agosto 2012 - 06:00

Conocía las funciones que mencionas TRUNC y TO_DATE por referencias a algunas lecturas, pero es muy apropiado para lo que mencionas.

Queda muy claro lo del DATA ;)


Saludos!
  • 0

#11 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 07 agosto 2012 - 08:26

Gracias compañeros por sus aportes y experiencias, siempre es bueno conocer este tipo de detalles.

Ahora bien, retornando un poco a la idea original y dando en cierta forma solución a la solicitud de consulta he realizado lo siguiente (presto a cualquier corrección claro está)


SELECT ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION, COUNT(*) FROM LLAMADAS_CLIENTE WHERE SOLUCIONADO = 1 AND FECHA BETWEEN '01/08/2012' AND '07/08/2012'
GROUP BY ID_LLAMADAS, ID_CLIENTE, ID_STAFF, ID_SOLUCION ORDER BY ID_STAFF DESC


suponiendo por la aclaración de Rolphy, este no tendría diferencia en Oracle.

Otra de las cosas por aplicar es en el manejo de bucles. En Firebird existe la operación for select que realiza una consulta previa y con el resultado realiza la operación iteractiva que tengamos dentro. ¿De qué manera se emplea en Oracle?


Saludos!


Si el bucle "ciclo" en méxico está destinado a recorrer un dataset... no es mejor hacer uso de cursores?

  • 0

#12 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 08 agosto 2012 - 07:47

Por lo general yo he trabajado en ciclos for sobre consultas simples, según la documentación de Firebird dice lo siguiente:

"for select" ejecuta una instrucción SELECT y recupera el conjunto de resultados. En cada iteración del bucle, los valores de campo de la fila actual se copian en variables locales. Con la adición de una cláusula AS CURSOR permite eliminaciones por posición y actualizaciones.


Suponiendo un ejemplo:


...
DECLARE VARIABLE SOL INT;
DECLARE VARIABLE CONT INT;
BEGIN
CONT = 0;
FOR SELECT SOLUCIONADO FROM LLAMADAS_CLIENTE WHERE FECHA BETWEEN '01/08/2012' AND '08/08/2012' INTO :SOL
DO
  BEGIN
    IF (SOL = 1) THEN CONT = CONT + 1; -- 1 para solucionado 0 para no solucionado
    SUSPEND;
  END
END


Y que éste retorne el total de esa variable cont.

Si bien los cursores en Firebird no son tema tan complejo, este es un ejemplo tomado de: http://www.firebirds...ql-declare.html

execute block
returns (relation char(31), sysflag int)
as
declare cur cursor for
  (select rdb$relation_name, rdb$system_flag from rdb$relations);
begin
  open cur;
  while (1=1) do
  begin
    fetch cur into relation, sysflag;
    if (row_count = 0) then leave;
    suspend;
  end
  close cur;
end


Creo que el while(1=1) del ejemplo tiene una solución más elegante en Oracle con el uso de LOOP, que hace de ciclo infinito.

Cualquier recomendación de método y explicación es válida compañero  :)



Saludos!
  • 0

#13 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.084 mensajes
  • LocationRepública Dominicana

Escrito 08 agosto 2012 - 07:55

Saludos.

Hasta donde mi conocimiento me permite llegar, en Firebird el uso de For Select o Cursor es igual.

Sin embargo, para Oracle es diferente el uso de For Loop y Cursor.  El primero no retorna un DataSet perse y el segundo si.
  • 0

#14 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 08 agosto 2012 - 08:18

Entonces Rolphy para ese caso es la recomendacion que haces del DATA.

Esperemos que agrega poliburro


Saludos!
  • 0

#15 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.084 mensajes
  • LocationRepública Dominicana

Escrito 08 agosto 2012 - 08:22

Saludos.

Si estimado, particularmente usaría el FOR LOOP.
  • 0

#16 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 08 agosto 2012 - 02:38

Según he leído en otras páginas la opción recomendable es usar el cursor implícito del for loop (y)


Saludos!
  • 0

#17 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 08 agosto 2012 - 02:49

Pues depende amigo... si necesitas un dataset en el que puedas hacer recorridos múltiples (adelante, atras, prionciio, fin) lo mejor será un cursor.. si se trata de solo un cursor de lectura de una sola corrida un loop será mejor.
  • 0

#18 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 08 agosto 2012 - 02:57

Pues depende amigo... si necesitas un dataset en el que puedas hacer recorridos múltiples (adelante, atras, prionciio, fin) lo mejor será un cursor.. si se trata de solo un cursor de lectura de una sola corrida un loop será mejor.


Todo muy claro (y)


Saludos!
  • 0

#19 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 08 agosto 2012 - 03:54

Si alguien más sigue este hilo y como yo no tiene mucha experiencia en PL/SQL, aquí les dejo este enlace para la creación y uso de cursores:

http://www.devjoker....s-en-PLSQL.aspx



Saludos!
  • 0

#20 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 08 agosto 2012 - 04:28

Ya que andas en eso amigo mio... Es posible vincular dos servidores Firebird para poder hacer consultas entre sus respectivas tablas?

algo como

     Select *
        From Server1.Database.Tabla1 As TablaUno
LEFT JOIN  Server2.Database.Tabla1 As TablaDos
        on TablaUno.Id = TablaDos.Id
where TablaDos.Id

  • 0