Procedimiento almacenado de Firebird para concatenar todos los valores de campo de varias filas
-
06-07-2019 - |
Pregunta
mi objetivo es escribir un proceso almacenado que pueda recopilar todos los valores de campo de varias filas en una sola variable de salida (tal vez varchar (some_length)). Puede parecer una solución extraña, pero estoy bastante seguro de que es la única que puedo usar en esa situación. No he usado Firebird antes y los procedimientos almacenados se ven muy diferentes a los de otros sistemas de db conocidos. Mi Firebird es 1.5 y dialecto 3 (no estoy seguro de lo que significa). Entonces, tal vez alguien podría ayudarme con un ejemplo de algoritmo.
Solución
El siguiente procedimiento hace lo que usted describe:
SET TERM !!;
CREATE PROCEDURE concat_names
RETURNS (concat VARCHAR(2000))
AS
DECLARE VARIABLE name VARCHAR(100);
BEGIN
concat = '';
FOR SELECT first_name || ' ' || last_name FROM employee INTO :name
DO BEGIN
concat = concat || name || ', ';
END
END!!
SET TERM ;!!
EXECUTE PROCEDURE concat_names;
Pero cuestiono la sabiduría de esta solución. ¿Cómo sabe que VARCHAR es lo suficientemente largo para todas las filas en su conjunto de datos deseado?
Es mucho más fácil y seguro ejecutar una consulta para devolver el resultado a una aplicación fila por fila. Cada lenguaje de programación de aplicaciones tiene métodos para concatenar cadenas, pero lo más importante es que tienen métodos más flexibles para administrar el crecimiento de los datos.
Por cierto, " dialecto " en Firebird e InterBase se refiere a un modo de compatibilidad que se introdujo para que las aplicaciones desarrolladas para InterBase 5.x puedan funcionar con versiones posteriores de InterBase y Firebird. Eso fue hace casi diez años, y AFAIK hoy no hay necesidad de usar nada más bajo que el dialecto 3.
Otros consejos
Debe probar los valores nulos al concatenar, aquí hay un ejemplo para dos campos y un separador entre ellos:
CREATE PROCEDURE CONCAT(
F1 VARCHAR(385),
F2 VARCHAR(385),
SEPARATOR VARCHAR(10))
RETURNS (
RESULT VARCHAR(780))
AS
begin
if ((:f1 is not null) and (:f1 <> '')) then
result = :f1;
if ((:f2 is not null) and (:f2 <> '')) then
if ((result is not null) and (result <> '')) then
begin
if ((:separator is not null) and (separator <> '')) then
result = result||separator||f2;
else
result = result||f2;
end
else
result = f2;
suspend;
end
Devolver varias filas usando los procedimientos almacenados de Firebird es muy fácil.
No use:
execute procedure proc_name(value);
En su lugar use:
select * from proc_name(value);