解决存储过程中的单例错误
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
是可选的(因为它是单个语句),但我更喜欢始终包含它们。
我在 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
是可选的(因为它是单个语句),但我更喜欢始终包含它们。