问题描述
如何在 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