我创建了一个自定义类型
CREATE TYPE rc_test_type AS (a1 bigint);
和一个功能
CREATE OR REPLACE FUNCTION public.rc_test_type_function(test_table character varying, dummy integer)
RETURNS rc_test_type AS
$BODY$
DECLARE
ret rc_test_type;
query text;
BEGIN
query := 'SELECT count(*) from ' || test_table ;
EXECUTE query into ret.a1;
RETURN ret;
END $BODY$
LANGUAGE plpgsql VOLATILE
如果我跑
SELECT * FROM rc_test_type_function('some_table', 1);
我得到了
"a1"
1389
到目前为止一切顺利。
如果我跑
SELECT p FROM (SELECT rc_test_type_function('some_table', s.step) AS p
FROM some_other_table s) foo;
我得到了
"p"
"(1389)"
"(1389)"
因为'some_other_table'只有两条记录。细
但是如果我尝试
SELECT p.a1 FROM (select rc_test_type_function('some_table', s.step) AS p
FROM some_other_table s) foo;
我收到错误
在子查询中缺少FROM子句条目表»p <<
我觉得奇怪,因为子查询没有改变。
两个问题:
a1
?答案 0 :(得分:2)
围绕复合类型使用括号:
SELECT (p).a1
FROM (SELECT rc_test_type_function('some_table', s.step) AS p
FROM some_other_table s
) foo;
即使您的类型只有一个列仍然是复合类型 - 具有自己的列名称。没有多大意义,但这就是你建造它的方式
(您可能只想使用简单类型或DOMAIN
代替。)
(compositecol).somefield
(mytable.compositecol).somefield
此处需要括号表示
compositecol
是列名而不是a 表名,或mytable
是表名而不是第二种情况下的模式名。
省略具有复合类型的零件,您的功能将更安全,更简单,更快:
CREATE OR REPLACE FUNCTION foo(test_table varchar, dummy int, OUT p bigint)
AS
$func$
BEGIN
EXECUTE format('SELECT count(*) from %I', test_table) -- !avoid SQLi!
INTO p;
END
$func$ LANGUAGE plpgsql;
OUT
parameter简化了语法。您根本不需要DECLARE
子句,也不需要RETURN
CREATE OR REPLACE FUNCTION foo(test_table regclass, dummy int, OUT p bigint)
AS
$func$
BEGIN
EXECUTE 'SELECT count(*) from ' || test_table
INTO p;
END
$func$ LANGUAGE plpgsql;
regclass
,这也适用于模式限定的表名。并且SQLi开始时不可能。如果表名是非法的,则该函数会立即失败,并在自动转换为text
时自动引用。