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;
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;
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