This isn't possible. Firebird needs to know at compile time which variable it is going to use. Dynamically referencing the output parameter is not possible.
As an intermediate solution, you could assign the result to a temporary variable, and then only do the assignment to the right variable in a long chain of if-else
. It is still code duplication but less than repeating the query over and over.
You could also execute a single query that produces the results for all months at once. This would lead to a slight code bloat, but probably be more efficient:
select
(SELECT count(*) from MY_TABLE where MONTH_ID = 1),
(SELECT count(*) from MY_TABLE where MONTH_ID = 2),
(SELECT count(*) from MY_TABLE where MONTH_ID = 3),
-- ...and so on
into :O_PARAM_1, :O_PARAM_2, :O_PARAM_3;
If you used a more recent Firebird version like Firebird 2.5, you could use a CTE (although for this simple query it doesn't simplify it a lot):
WITH counts AS (SELECT MONTH_ID, count(*) AS MONTH_COUNT from MY_TABLE M GROUP BY MONTH_ID)
select
(SELECT MONTH_COUNT from counts where MONTH_ID = 1),
(SELECT MONTH_COUNT from counts where MONTH_ID = 2),
(SELECT MONTH_COUNT from counts where MONTH_ID = 3),
-- ...and so on
into :O_PARAM_1, :O_PARAM_2, :O_PARAM_3;
A totally different solution would be to abandon the idea of an executable stored procedure (although with the presence of SUSPEND
in your current solution it is actually selectable with always one row), and instead use a selectable procedure that returns the result as rows. If that is a solution depends on your actual data needs.
CREATE PROCEDURE MY_PROC (
I_PARAM INTEGER)
RETURNS (
MONTH_ID INTEGER, MONTH_COUNT INTEGER)
AS
BEGIN
FOR
select MONTH_ID, count(*)
from MY_TABLE M
GROUP BY MONTH_ID
into :MONTH_ID, :MONTH_COUNT
BEGIN
SUSPEND;
END
END