在 PostgreSQL 中,我收到错误:
ERROR: argument for function "exp" too big
SQL state: 22003
我需要为指数编写一个存储过程:
- 如果
exp(value)
函数“exp”的抛出参数太大 - 然后返回 0
- 否则返回
exp(value)
请帮助我如何处理这个存储过程。
在 PostgreSQL 中,我收到错误:
ERROR: argument for function "exp" too big
SQL state: 22003
我需要为指数编写一个存储过程:
exp(value)
函数“exp”的抛出参数太大exp(value)
请帮助我如何处理这个存储过程。
这就是正在发生的事情:
regress=# SELECT exp(NUMERIC '6000');
ERROR: argument for function "exp" too big
您将一个不切实际的大值传递给exp()
. 它太大而无法溢出float8
(double) 并且只能表示为NUMERIC
. 即使在那里,也有一个限制,当你超过时你就会达到它exp(5999)
。
对于硬数学,您可能想尝试该语言PL/R
的数据库内嵌入式版本。R
很难说要做什么,因为您还没有真正解释查询的用途,输入exp
应该是什么等。
为太大的指数返回零有点疯狂。为什么?
要捕获异常,请在 PL/PgSQL 中使用BEGIN ... EXCEPTION 。
我编写了下面的函数来返回NaN
(“不是数字”)而不是零,因为我认为返回零是完全错误的。如果需要,请更改它。返回也可能有点意义NULL
。
CREATE OR REPLACE FUNCTION exp_if_possible(numeric) RETURNS numeric as $$
BEGIN
RETURN exp($1);
EXCEPTION
WHEN numeric_value_out_of_range THEN
RETURN 'NaN';
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
错误代码是通过在 Pg 手册中的附录 A.PostgreSQL 错误代码numeric_value_out_of_range
中查找SQLSTATE 22003
您从超出范围exp
中获得的信息而获得的。您将在有关.BEGIN ... EXCEPTION
我最初说如果要完成它应该通过测试输入来完成,但我认为我错了。不能保证限制会是exp(6000)
,所以你使用异常处理是正确的,即使它会很慢而且很笨拙。我将在几秒钟内使用异常处理版本更新此响应。
CREATE OR REPLACE FUNCTION crazy_exp(numeric) RETURNS numeric AS $$
-- exp(6000) and above will throw 'argument for function "Exp" too big
-- For such cases, return zero because [insert explanation here]
SELECT CASE WHEN $1 < 6000 THEN exp($1) ELSE 0 END;
$$ LANGUAGE 'sql' IMMUTABLE;
CREATE OR REPLACE FUNCTION crazy_exp(float8) RETURNS float8 AS $$
-- float8 goes out-of-range above about exp(600)
SELECT CASE WHEN $1 <= 600 THEN exp($1) ELSE 0 END;
$$ LANGUAGE 'sql' IMMUTABLE;
这比在 PL/ PgSQL中捕获“超出范围”异常要高效得多,并且也使您的意图更加清晰。