【发布时间】:2017-03-28 02:42:41
【问题描述】:
我有以下使用 PostgreSQL 视图的案例。我必须根据另一个动态计算的视图列的值来动态计算视图列的值。这是代码的简化版本:
BEGIN;
CREATE TABLE test
(
id serial PRIMARY KEY,
value integer NOT NULL
);
INSERT INTO test VALUES
(1, 13),
(2, 42);
CREATE FUNCTION inc(value integer)
RETURNS integer AS
$BODY$
BEGIN
RETURN value + 1;
END;
$BODY$
LANGUAGE plpgsql;
CREATE FUNCTION double(id integer)
RETURNS integer AS
$BODY$
DECLARE
local_value integer;
BEGIN
SELECT value_1 INTO local_value
FROM test_view WHERE double.id = test_view.id;
RETURN 2 * local_value;
END;
$BODY$
LANGUAGE plpgsql;
CREATE VIEW test_view AS
SELECT *,
inc(test.value) AS value_1,
double(test.id) AS value_2
FROM test;
COMMIT;
但是由于第二个函数中的以下语句,这段代码陷入了无限递归。
SELECT value_1 INTO local_value
FROM test_view WHERE double.id = test_view.id;
确切的错误如下:
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth
(currently 2048kB), after ensuring the platform's stack depth limit is adequate.
CONTEXT: PL/pgSQL function inc(integer) line 3 at RETURN
SQL statement "SELECT value_1 FROM test_view WHERE double.id = test_view.id"
PL/pgSQL function double(integer) line 5 at SQL statement
使用第二个视图可以轻松解决该问题。例如:
CREATE FUNCTION double(value integer)
RETURNS integer AS
$BODY$
BEGIN
RETURN 2 * value;
END;
$BODY$
LANGUAGE plpgsql;
CREATE VIEW test_view_1 AS
SELECT *,
inc(test.value) AS value_1
FROM test;
CREATE VIEW test_view_2 AS
SELECT *,
double(test_view_1.value_1) AS value_2
FROM test_view_1;
但我不喜欢这种方法,因为它需要创建第二个视图。如果我有 n 个不同的值,每个值都取决于前一个值,它不会缩放。那么我一定有n种不同的观点。
只有一个视图可以解决问题吗?
【问题讨论】:
标签: database postgresql recursion sql-view dynamic-columns