我有一个存储过程RETURNS record
:
CREATE OR REPLACE FUNCTION r_rpt_prov_summary()
RETURNS record
AS $$
DECLARE
_fields record;
BEGIN
SELECT INTO _fields
0::integer AS customers,
0::integer AS customers_active;
SELECT INTO _fields.customers count(*) FROM customer;
SELECT INTO _fields.customers_active count(*) FROM customer WHERE active = 't';
RETURN _fields;
END
$$ LANGUAGE 'plpgsql';
但是,为了查询它,我必须显式枚举返回的列和类型:
SELECT * FROM r_rpt_prov_summary() AS (a integer, b integer);
为了使这个对 MVC 框架来说是可口的,它本质上想要查询表,我将它包装在一个SQL
函数中RETURNS TABLE
:
CREATE OR REPLACE FUNCTION rpt_prov_summary()
RETURNS TABLE (
customers integer,
customers_active integer
) AS $$
SELECT * FROM r_rpt_prov_summary() AS (customers integer, customers_active integer);
$$ LANGUAGE 'sql';
只要这两个函数驻留在相同的模式或search_path
空间中,这就会非常有效。但是,在这种情况下,他们生活在自己的非标准模式中,所以我必须将外部函数查询为myschema.rpt_prov_summary()
,即
SELECT * FROM myschema.rpt_prov_summary();
如果我的架构和搜索路径设置为:这不起作用public
:
test=> SELECT * FROM myschema.rpt_prov_summary();
ERROR: function r_rpt_prov_summary() does not exist
LINE 2: SELECT * FROM r_rpt_prov_summary() AS (customers integer, ...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
自然,您的想法会转向调用SET SCHEMA 'myschema'
或SET search_path TO myschema
查询执行之前。我的也是。问题是它不适用于我打电话的环境。MVC 框架使用准备好的语句来构造查询,而 PostgreSQL 不赞成这样的事情:
SET search_path TO myschema;SELECT * FROM rpt_prov_summary();
也就是说:
< 2016-03-14 20:50:46.410 EDT >ERROR: cannot insert multiple commands into a prepared statement
所以,这是行不通的。将模式作为外部函数的参数提供也不起作用;我只是在 MVC 框架的约束下没有那种灵活性,它想要查询普通的旧表或像表一样的东西。
current_schema
标识客户端会话的当前模式,因此这无济于事。已经尝试过这个:
CREATE OR REPLACE FUNCTION rpt_prov_summary()
RETURNS TABLE (
customers integer,
customers_active integer
) AS $$
BEGIN
RAISE NOTICE 'Current schema: %', current_schema;
RETURN QUERY EXECUTE 'SELECT * FROM ' || current_schema || '.r_rpt_prov_summary() AS (customers integer, customers_active integer)';
END
$$ LANGUAGE 'plpgsql';
没有骰子 - Current schema: public
,正如预期的那样。
有没有办法以某种方式捕获外部调用的模式空间并将其传播到封装的查询中?