通过一个简单的例子学习在 Firebird 中使用执行块

Learning to use execute block in Firebird with a simple example

我还没有在 Firebird 中使用过执行块,但我正在努力学习如何使用它。

我试图从一个简单的例子中学习,然后扩展到更复杂的情况。

假设我有 2 个 table,如下所示:

+------------+------+
| Clientcode | name |
+------------+------+
|        123 | A    |
|        234 | B    |
+------------+------+
+----------+------------+---------+
| order_id | clientcode |  value  |
+----------+------------+---------+
|       12 |        234 |  10,00  |
|       13 |        123 |  20,00  |
|       14 |        123 |  10,00  |
+----------+------------+---------+

我有以下代码。

execute block returns (client integer,amount double)
as
declare variable  client_code integer;
begin
for
select clientcode from clients
into  : client_code
do
begin
select :client_code,sum(value) from orders group by 1
into :client, :order_id;
end
end

基本上,我想为客户端table中的每个客户端计算订单table中的订单总和。我知道在这种情况下不需要执行块,但是通过一个简单的例子我可能会更好地理解它。

+-------------+--------+
| client_code | amount |
+-------------+--------+
|         123 |     30 |
|         234 |     10 |
+-------------+--------+

正确的语法是什么?

您的代码中缺少一些东西:

  1. orders 中选择时需要一个 where 子句以将其限制为仅当前客户端的行
  2. 您需要将总和输出到 amount,而不是 non-existent 变量 order_id
  3. 您需要添加 suspend 以输出一行(否则执行块只能产生一行,并分配最后一个值)。
  4. (可选)当 client 达到相同目的时,您不需要变量 client_code

生成的代码类似于(请注意,我使用 decimal(18,2) 而不是 double precision,使用 decimal 等精确数字类型是货币值的更好选择):

execute block returns (client_code integer,amount decimal(18,2))
as
begin
  for select clientcode from clients 
    into client_code
  do
  begin
    select sum(amount) from orders where clientcode = :client_code
      into amount;
    suspend;
  end
end

这相当于以下查询:

select clients.clientcode as client_code, sum(orders.amount) as amount
from clients
left join orders on clients.clientcode = orders.clientcode
group by clients.clientcode

另请参阅此 dbfiddle

请记住,execute block is essentially a Firebird stored procedure that isn't stored. An execute block with a suspend behaves as a selectable procedure which can produce zero or more rows, and one without suspend behaves as an executable procedure 只能生成一行。