与PL/pgSQL
函数不同,语言SQL
的函数接受记录和记录数组。以下脚本有效:
create type testtyp1 as ( a int, b unknown );
create type testtyp2 as ( a int, b text );
create type testtyp3 as ( a int, b varchar(8000) );
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select 'x'::text;
$$ LANGUAGE sql;
-- the function should support all these:
select xdecode( (1,'a'),(2,'b') );
select xdecode( (1,'a')::testtyp1, (2,'b')::testtyp1 );
select xdecode( (1,'a')::testtyp2, (2,'b')::testtyp2 );
select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
同样重要的是:
select xdecode( (0.1,now()), (0.2,now()) );
现在,我需要更改函数,以便它返回其第一列符合特定条件的数组元素的第二列。
问题在于记录列可以具有任何名称或完全没有名称。另一个问题是PostgreSQL
中的字符常量具有类型:unknown
。
如果我尝试将行强制转换为其他任何类型,则调用将失败,并显示以下信息:
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select args[1]::testtyp1::text
$$ LANGUAGE sql;
...
> select xdecode( (1,'a'),(2,'b') );
cannot cast type record to testtyp1
> select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
cannot cast type testtyp3 to testtyp1
我可以通过一个辅助函数来避免不知道列名:
create or replace function hlp(arg anyelement) RETURNS record AS $$
select arg;
$$ LANGUAGE sql;
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select b::text from hlp( args[1] ) AS T(a int , b unknown);
$$ LANGUAGE sql;
但是我不知道是unknown
还是text
:
> select xdecode( (1,'a'),(2,'b') );
a
> select xdecode( (1,'a')::testtyp1, (2,'b')::testtyp1 );
a
> select xdecode( (1,'a')::testtyp2, (2,'b')::testtyp2 );
Returned type text at ordinal position 2, but query expects unknown.
> select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
Returned type text at ordinal position 2, but query expects unknown.
不能指定类型:
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select b::text from hlp( args[1] ) AS T(a, b);
$$ LANGUAGE sql;
> select xdecode( (1,'a'),(2,'b') );
a column definition list is required for functions returning "record"