我有一张空桌子
stock_holdings
:
select qty,total_amount from stock_holdings where account_id=1 and ticker_cd='XYZ';
qty | total_amount
-----+--------------
(0 rows)
当我运行以下 PL/pgSQL 代码块时,异常应该处理这种情况。但是,我得到以下结果:
NOTICE: before v_qty: -100
NOTICE: before v_total_amount: -1000
NOTICE: after v_qty: <NULL>
NOTICE: after v_total_amount: <NULL>
DO
Query returned successfully in 70 msec.
代码块如下所示:
do
language plpgsql
$$
declare
v_qty numeric := -100;
v_total_amount numeric := -1000;
begin
raise notice 'before v_qty: %', v_qty;
raise notice 'before v_total_amount: %', v_total_amount;
SELECT qty,total_amount INTO v_qty,v_total_amount
FROM stock_holdings
WHERE account_id = 1 AND ticker_cd = 'XYZ';
raise notice 'after v_qty: %', v_qty;
raise notice 'after v_total_amount: %', v_total_amount;
exception
when NO_DATA_FOUND then
raise notice 'No data found error: %', sqlstate;
when others then
raise notice 'Other error: %', sqlstate;
end;
$$
您需要使用
STRICT
关键字,否则如果查询没有返回行,则表达式会将变量设置为 NULL
。
例如。
SELECT qty,total_amount INTO STRICT v_qty, v_total_amount FROM stock_holding;
参见 https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATMENTS-SQL-ONEROW
虽然您也可以使用特殊的
FOUND
变量,如果查询返回一行或更多行,则该变量设置为
true
。如果您使用 STRICT
关键字,则当查询返回多于一行时,会引发 TOO_MANY_ROWS
异常。
例如。
SELECT qty,total_amount INTO v_qty, v_total_amount FROM stock_holding;
IF NOT FOUND THEN
-- logic for handling if no value for v_qty and v_total_amount
END IF;
要让
select
加注 NO_DATA_FOUND
,您必须使用 strict
选项。目的是当您期望恰好返回 ONE 行时。
如果指定了 STRICT 选项,则该命令必须恰好返回一行,否则将报告运行时错误,NO_DATA_FOUND(无行)或 TOO_MANY_ROWS(多于一行)...
SELECT qty,total_amount
INTO STRICT v_qty,v_total_amount
FROM stock_holdings
WHERE account_id = 1
AND ticker_cd = 'XYZ';
示范.
STRICT
来引发异常,但这通常是错误的方法。引发控制流异常的成本高昂且具有破坏性。 手册警告:
包含
子句的块明显更多 进入和退出比没有进入和退出的街区昂贵。因此,不要 无需使用EXCEPTION
。EXCEPTION
FOUND
实现更简单、更便宜的控制流程:
DO
$do$
DECLARE
v_qty numeric := -100;
BEGIN
RAISE NOTICE 'before v_qty: %', v_qty;
SELECT s.qty
INTO v_qty
FROM stock_holdings s
WHERE s.account_id = 1
AND s.ticker_cd = 'XYZ';
RAISE NOTICE 'after v_qty: %', v_qty;
-- do NOT raise an exception!
IF NOT FOUND THEN
RAISE NOTICE 'No data found (no error)';
END IF;
-- no reason to add an expensive EXCEPTION clause
END
$do$;
相关: