从 PL/pgSQL 中的函数调用 table 函数 - 这可能吗?
Call table functions from function in PL/pgSQL - is that possible?
我有两个类似的函数,结果相同 table,我想创建一个函数来选择要执行的函数。
我的函数是从如下代码创建的 - function_a
和 function_b
:
CREATE OR REPLACE FUNCTION function_a(sys_id integer)
RETURNS TABLE (
col_1 text,
col_2 text,
col_3 text) AS $$
(...)
END; $$
LANGUAGE 'plpgsql';
我想得到这样的东西(这段代码不起作用,但我认为它表达了我的意图):
CREATE OR REPLACE FUNCTION choose_function(system text, sys_id integer)
RETURNS TABLE (
col_1 text,
col_2 text,
col_3 text) AS $$
BEGIN
IF system = 'A' THEN RETURN
(select * from function_a(sys_id));
ELSEIF system = 'B' THEN RETURN
(select * from function_b(sys_id));
END IF;
END; $$
LANGUAGE 'plpgsql';
我收到一个错误:
ERROR: RETURN cannot have a parameter in function returning set
并提示:
HINT: Use RETURN NEXT or RETURN QUERY.
但是使用 RETURN QUERY
导致我收到空的 table 或者更确切地说 headers 并且使用 RETURN NEXT
也给我一个错误:ERROR: RETURN NEXT cannot have a parameter in function with OUT parameters
.
是否可以满足我的需求?
没有问题是可以的。每个函数都有自己的输出栈——顶层函数的输出栈是可见的结果。没有一个全局输出堆栈。所以你不能调用 table 函数而不将它们的结果存储在调用者输出堆栈中。这可以通过命令 RETURN QUERY
:
来完成
CREATE OR REPLACE FUNCTION f_a(a int)
RETURNS TABLE (b int, c int) AS
$$
SELECT i, i+1 FROM generate_series(1,a)
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION f_b(a int)
RETURNS TABLE (b int, c int) AS
$$
SELECT i, i*10 FROM generate_series(1,a)
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION f2(par1 text, a int)
RETURNS TABLE (b int, c int) AS
$$
BEGIN
IF par1 = 'A' THEN
RETURN QUERY SELECT * FROM f_a(a);
ELSE
RETURN QUERY SELECT * FROM f_b(a);
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE test(par1 text, a int);
INSERT INTO test('a', 10);
INSERT INTO test('b', 3);
SELECT f2.* FROM test, LATERAL f2(par1, a);
我有两个类似的函数,结果相同 table,我想创建一个函数来选择要执行的函数。
我的函数是从如下代码创建的 - function_a
和 function_b
:
CREATE OR REPLACE FUNCTION function_a(sys_id integer)
RETURNS TABLE (
col_1 text,
col_2 text,
col_3 text) AS $$
(...)
END; $$
LANGUAGE 'plpgsql';
我想得到这样的东西(这段代码不起作用,但我认为它表达了我的意图):
CREATE OR REPLACE FUNCTION choose_function(system text, sys_id integer)
RETURNS TABLE (
col_1 text,
col_2 text,
col_3 text) AS $$
BEGIN
IF system = 'A' THEN RETURN
(select * from function_a(sys_id));
ELSEIF system = 'B' THEN RETURN
(select * from function_b(sys_id));
END IF;
END; $$
LANGUAGE 'plpgsql';
我收到一个错误:
ERROR: RETURN cannot have a parameter in function returning set
并提示:
HINT: Use RETURN NEXT or RETURN QUERY.
但是使用 RETURN QUERY
导致我收到空的 table 或者更确切地说 headers 并且使用 RETURN NEXT
也给我一个错误:ERROR: RETURN NEXT cannot have a parameter in function with OUT parameters
.
是否可以满足我的需求?
没有问题是可以的。每个函数都有自己的输出栈——顶层函数的输出栈是可见的结果。没有一个全局输出堆栈。所以你不能调用 table 函数而不将它们的结果存储在调用者输出堆栈中。这可以通过命令 RETURN QUERY
:
CREATE OR REPLACE FUNCTION f_a(a int)
RETURNS TABLE (b int, c int) AS
$$
SELECT i, i+1 FROM generate_series(1,a)
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION f_b(a int)
RETURNS TABLE (b int, c int) AS
$$
SELECT i, i*10 FROM generate_series(1,a)
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION f2(par1 text, a int)
RETURNS TABLE (b int, c int) AS
$$
BEGIN
IF par1 = 'A' THEN
RETURN QUERY SELECT * FROM f_a(a);
ELSE
RETURN QUERY SELECT * FROM f_b(a);
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE test(par1 text, a int);
INSERT INTO test('a', 10);
INSERT INTO test('b', 3);
SELECT f2.* FROM test, LATERAL f2(par1, a);