解决存储过程中的单例错误

Resolving a singleton error in a stored procedure

我在 Firebird 中有以下存储过程 SQL:

ALTER PROCEDURE SP_REPORT_USD
(
  PER SMALLINT
)
RETURNS
(
  ACCOUNT_NUMBER CHAR(21),
  AMOUNT NUMERIC(15, 4)
  )

AS

BEGIN

SELECT
      L.ACCOUNT_NUMBER, SUM(CURRROUND(L.DEBIT,2)-CURRROUND(L.CREDIT,2))
   FROM
      LEDGER L
   WHERE
      L.LEDGER_ACCOUNT = '31621' AND L.PERIOD = :PER
   GROUP BY
      L.ACCOUNT_NUMBER

   INTO
      ACCOUNT_NUMBER, AMOUNT;

SUSPEND;

END

当我运行以下查询时:

SELECT * FROM SP_REPORT_USD('17')

我收到以下错误:

MULTIPLE ROWS IN SINGLETON SELECT
AT PROCEDURE 'SP_REPORT_USD' LINE: 15, COL: 1

第 15 列第 1 行是我的 select 语句在执行存储过程时开始的地方。

我确实测试了以下查询:

SELECT
   L.ACCOUNT_NUMBER, INV.DESCRIPTION, SUM(-(CURRROUND(L.DEBIT,2) - CURRROUND(L.CREDIT,2)))
FROM
   LEDGER L join INVENTORY INV ON L.ACCOUNT_NUMBER = INV.STOCK_CODE
WHERE
   L.LEDGER_ACCOUNT = '31621' AND L.PERIOD = 17
GROUP BY
   L.ACCOUNT_NUMBER, INV.DESCRIPTION

并且结果符合预期。所以我知道我的查询逻辑是正确的,我只是在存储过程上做错了。

如有任何帮助,我们将不胜感激。

问题在于,在存储过程中,SELECT 语句仅用于 select 单个行中的值(所谓的单例 select)。您的查询生成多行,因此出现错误 "multiple rows in singleton select".

如果要产生多行,需要使用FOR SELECT语句,并且SUSPEND语句必须在这个FOR SELECT语句的主体中:

ALTER PROCEDURE SP_REPORT_USD(PER SMALLINT)
  RETURNS (ACCOUNT_NUMBER CHAR(21), AMOUNT NUMERIC(15, 4))
AS
BEGIN
   FOR 
     SELECT L.ACCOUNT_NUMBER, SUM(CURRROUND(L.DEBIT,2)-CURRROUND(L.CREDIT,2))
     FROM LEDGER L
     WHERE L.LEDGER_ACCOUNT = '31621' AND L.PERIOD = :PER
     GROUP BY L.ACCOUNT_NUMBER
     INTO :ACCOUNT_NUMBER, :AMOUNT 
   DO
   BEGIN
     SUSPEND;
   END
END

在这种情况下,SUSPEND; 周围的 BEGIN...END 是可选的(因为它是单个语句),但我更喜欢始终包含它们。