views:

2828

answers:

2

Hi, my goal is to write a stored proc that can collect all field values from multiple rows into one single output variable (maybe varchar(some_length)). It may seem strange solution but i've quite positive its the only one i can use at that situation im in. I have not used Firebird before and stored procs look way different than in other well-known db systems. My Firebird is 1.5 and dialect 3 (not sure what it means). So maybe someone could help me with a algorithm example.

+2  A: 

The following procedure does what you 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;

But I question the wisdom of this solution. How do you know the VARCHAR is long enough for all the rows in your desired dataset?

It's far easier and safer to run a query to return the result to an application row by row. Every application programming language has methods to concatenate strings, but more importantly they have more flexible methods to manage the growth of data.

By the way, "dialect" in Firebird and InterBase refers to a compatibility mode that was introduced so that applications developed for InterBase 5.x can work with later versions of InterBase and Firebird. That was almost ten years ago, and AFAIK there's no need today to use anything lower than dialect 3.

Bill Karwin
If you use Firebird 2.1, you can use the LIST aggregate function with provides textual BLOB as a result. I.e. no limit of varchar field.
Milan Babuškov
If I recall, you can't declare a procedure parameter or return value with a BLOB or ARRAY data type.
Bill Karwin
Any null value would break this solution.
Nelson
@Nelson: Yes, you're right. If the fields can be null, the expressions must use `COALESCE()` to fold them into a non-null value.
Bill Karwin
A: 

You have to test for null values when concatenating, here is an example for two fields and a separator between them:

    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
atika