使用execute语句带索引变量的Firebird存储过程

问题描述

如何在 Firebird 存储过程中使用索引变量?我的意思是,我有输出参数 ODATE1、ODATE2、ODATE3,我可以用作 ':ODATE' || COUNTER 在循环中设置值?

我有两张这样的桌子:

    1. T_EMPLOYEE
    ---------------
    | ID_E | NAME |
    ---------------
    | 1    | Anne |
    ---------------
    | 2    | Bob  |
    ---------------


    2. T_WORK
    ----------------------------
    | ID_W | DATE_W     | ID_E |
    ----------------------------
    | 1    | 2021-01-01 | 1    |
    ----------------------------
    | 2    | 2021-01-01 | 2    |
    ----------------------------
    | 3    | 2021-01-02 | 1    |
    ----------------------------
    | 4    | 2021-01-03 | 2    |
    ----------------------------

我想从那个表中创建一个存储过程来得到这个结果:

    DASHBOARD
    -----------------------------------------------------------
    | OID_E | ONAME     | ODATE1     | ODATE2     | ODATE3     |
    ----------------------------------------------------------
    | 1     | Anne      |     1      |      1     |      0     |
    -----------------------------------------------------------
    | 2     | Bob       |     1      |      0     |      1     |
    -----------------------------------------------------------

我尝试在存储过程中像这样使用 EXECUTE STATEMENT

    DECLARE VARIABLE COUNTER INT;
    BEGIN

    FOR 
        SELECT ID_E,NAME FROM T_EMPLOYEE 
        INTO :OID_E,:ONAME
    D0
    BEGIN
        COUNTER = 1;
        WHILE (COUNTER<=3) DO
        BEGIN 
           EXECUTE STATEMENT 'SELECT COUNT(*) FROM T_WORK WHERE DATE_W = ''2021-01-0' || COUNTER ||
           ''' AND ID_E = ' || :OID_E || ' INTO :ODATE' || COUNTER;
    
           COUNTER = COUNTER + 1;
        END 
        SUSPEND;
    END 
    
    END  /*procedure*/

程序无法编译。 然后我尝试了这样的简单的没有 COUNTER 索引替换的:

    DECLARE VARIABLE COUNTER INT;
    BEGIN

    FOR 
        SELECT ID_E,:ONAME
    D0
    BEGIN
        COUNTER = 1;
        WHILE (COUNTER<=3) DO
        BEGIN 
           EXECUTE STATEMENT 'SELECT COUNT(*) FROM T_WORK WHERE ID_E = :OID_E ' ||
           ' AND DATE_W =''2021-01-02'' INTO :ODATE2';

           COUNTER = COUNTER + 1;
        END 
        SUSPEND;
    END 
    
    END  /*procedure*/

程序可以编译,但是当我执行时,它会引发这个错误

    sql Error:  Dynamic sql Error sql error code = @1 Token unkNown - line @1,column @2 @1. Error Code: -104. Invalid token

请多多指教。如何使用 EXECUTE STATEMENT 进行灵活循环以设置索引变量。 或者您有其他解决方案可以满足我的需求。

附加信息:Firebird v2.5

解决方法

您不能像这样动态引用 PSQL 变量(包括参数)。但是,您不需要跳过所有这些障碍来获得所需的结果。

您可以使用以下内容(甚至不需要过程):

select e.ID_E as OID_E,e.NAME as ONAME,count(case when w.DATE_W = date '2021-01-01' then 1 end) as ODATE1,count(case when w.DATE_W = date '2021-01-02' then 1 end) as ODATE2,count(case when w.DATE_W = date '2021-01-03' then 1 end) as ODATE3
from T_EMPLOYEE e
inner join T_WORK w
  on w.ID_E = e.ID_E
group by e.ID_E,e.NAME
order by e.ID_E

小提琴:https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=59066afc0fd7f6b5cb87eac99164e899