Tema: UDF Firebird
Ver Mensaje Individual
  #9  
Antiguo 10-03-2010
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Reputación: 24
guillotmarc Va por buen camino
Hola Casimiro.

Que yo sepa ha sido posible hacerlo desde siempre, desde Firebird 1 (que es cuando empecé a utilizar Interbase/Firebird). Que yo recuerde, en los procedimientos almacenados siempre se ha podido añadir el suspend (que normalmente utilizas con un for select) para que devuelva el resultado como un dataset.

Aunque esto normalmente se usa para leer un dataset en tu programa (en lugar de utilizando un select), también puedes utilizar el procedimiento almacenado dentro de un select, en una union, en una subconsulta, etc. ...

Así que un buen día me di cuenta de que eso podia ser muy útil, ya que además de utilizarlo para consultar datos también podría servir para definirme mi propia librería de funciones en PSQL, y no tener que depender tanto de udf's externas.

La verdad es que desde entonces lo vengo usando de forma masiva.

Me es especialmente imprescindible cuando tengo que importar datos. Muchas veces tengo que programar importaciones hacia nuestro sistema de las gestiones que puedan tener nuevos clientes. Con lo que te encuentras que tienes que trabajar con todo tipo de datos, y que muchas veces los clientes lo tiene en un simple campo de texto, mal formateado, y que te las tienes que apañar para convertirlo, por ejemplo, en un timestamp.

Por eso tengo una librería de funciones como esta (en este caso intenta convertir una cadena en fecha) :

Código SQL [-]
CREATE PROCEDURE "X_IMPORT_Data" (
    VALOR VARCHAR(50))
RETURNS (
    DATA TIMESTAMP)
AS
DECLARE VARIABLE DIA INTEGER;
DECLARE VARIABLE MES INTEGER;
DECLARE VARIABLE ANO INTEGER;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE TMP VARCHAR(50);
begin
  DATA = null;
  I = 1;
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  DIA = cast(TMP as integer);
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  MES = cast(TMP as integer);
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  ANO = cast(TMP as integer);
  if (:ANO < 20) then ANO = 2000 + ANO;              /* Tracto l'any, ja que pot estar en 2 digits */
  else if (:ANO < 100) then ANO = 1900 + ANO;
  TMP = cast(MES as varchar(20)) || '-' || cast(DIA as varchar(20)) || '-' || cast(ANO as varchar(20));
  DATA = cast(TMP as TIMESTAMP);
  suspend;
  when any do exit;    /* En cas d'Error retorno Null */
end
^

Creo una tablas temporales de importacion, con la estructura de los datos a importar, y hago un DataPump, con lo que ya tengo todos los datos en una única base de datos Firebird.

Luego ya solo tengo que hacer los correspondentes INSERT INTO *** SELECT **** FROM IMPORT_**** para poner los datos de las tablas temporales en las tables correspondientes de nuestro sistema, y puedo utilizar esas funciones como si fueran UDF's, con lo que he recortado drasticamente el tiempo que tardo en hacer una importacion de datos (antes me tenía que hacer un programa en Delphi ex-profeso en cada ocasión).

Saludos
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).

Última edición por guillotmarc fecha: 10-03-2010 a las 19:50:29.
Responder Con Cita